From 31b5dfe9eed3de15effd1998f0c004896652af39 Mon Sep 17 00:00:00 2001 From: Afshan Date: Fri, 9 Apr 2021 16:52:14 +0530 Subject: [PATCH 001/135] feat: Dimension-wise Accounts Balance Report --- .../__init__.py | 0 .../dimension_wise_accounts_balance_report.js | 81 +++++++ ...imension_wise_accounts_balance_report.json | 22 ++ .../dimension_wise_accounts_balance_report.py | 205 ++++++++++++++++++ 4 files changed, 308 insertions(+) create mode 100644 erpnext/accounts/report/dimension_wise_accounts_balance_report/__init__.py create mode 100644 erpnext/accounts/report/dimension_wise_accounts_balance_report/dimension_wise_accounts_balance_report.js create mode 100644 erpnext/accounts/report/dimension_wise_accounts_balance_report/dimension_wise_accounts_balance_report.json create mode 100644 erpnext/accounts/report/dimension_wise_accounts_balance_report/dimension_wise_accounts_balance_report.py diff --git a/erpnext/accounts/report/dimension_wise_accounts_balance_report/__init__.py b/erpnext/accounts/report/dimension_wise_accounts_balance_report/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/accounts/report/dimension_wise_accounts_balance_report/dimension_wise_accounts_balance_report.js b/erpnext/accounts/report/dimension_wise_accounts_balance_report/dimension_wise_accounts_balance_report.js new file mode 100644 index 00000000000..6a0394861b8 --- /dev/null +++ b/erpnext/accounts/report/dimension_wise_accounts_balance_report/dimension_wise_accounts_balance_report.js @@ -0,0 +1,81 @@ +// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt +/* eslint-disable */ + +frappe.require("assets/erpnext/js/financial_statements.js", function() { + frappe.query_reports["Dimension-wise Accounts Balance Report"] = { + "filters": [ + { + "fieldname": "company", + "label": __("Company"), + "fieldtype": "Link", + "options": "Company", + "default": frappe.defaults.get_user_default("Company"), + "reqd": 1 + }, + { + "fieldname": "fiscal_year", + "label": __("Fiscal Year"), + "fieldtype": "Link", + "options": "Fiscal Year", + "default": frappe.defaults.get_user_default("fiscal_year"), + "reqd": 1, + "on_change": function(query_report) { + var fiscal_year = query_report.get_values().fiscal_year; + if (!fiscal_year) { + return; + } + frappe.model.with_doc("Fiscal Year", fiscal_year, function(r) { + var fy = frappe.model.get_doc("Fiscal Year", fiscal_year); + frappe.query_report.set_filter_value({ + from_date: fy.year_start_date, + to_date: fy.year_end_date + }); + }); + } + }, + { + "fieldname": "from_date", + "label": __("From Date"), + "fieldtype": "Date", + "default": frappe.defaults.get_user_default("year_start_date"), + }, + { + "fieldname": "to_date", + "label": __("To Date"), + "fieldtype": "Date", + "default": frappe.defaults.get_user_default("year_end_date"), + }, + { + "fieldname": "finance_book", + "label": __("Finance Book"), + "fieldtype": "Link", + "options": "Finance Book", + }, + { + "fieldname": "dimension", + "label": __("Select Dimension"), + "fieldtype": "Select", + "options": get_accounting_dimension_options(), + "reqd": 1, + }, + ], + "formatter": erpnext.financial_statements.formatter, + "tree": true, + "name_field": "account", + "parent_field": "parent_account", + "initial_depth": 3 + } + +}); + +function get_accounting_dimension_options() { + let options =["", "Cost Center", "Project"]; + frappe.db.get_list('Accounting Dimension', + {fields:['document_type']}).then((res) => { + res.forEach((dimension) => { + options.push(dimension.document_type); + }); + }); + return options +} diff --git a/erpnext/accounts/report/dimension_wise_accounts_balance_report/dimension_wise_accounts_balance_report.json b/erpnext/accounts/report/dimension_wise_accounts_balance_report/dimension_wise_accounts_balance_report.json new file mode 100644 index 00000000000..6141944f9d2 --- /dev/null +++ b/erpnext/accounts/report/dimension_wise_accounts_balance_report/dimension_wise_accounts_balance_report.json @@ -0,0 +1,22 @@ +{ + "add_total_row": 0, + "columns": [], + "creation": "2021-04-09 16:48:59.548018", + "disable_prepared_report": 0, + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "filters": [], + "idx": 0, + "is_standard": "Yes", + "modified": "2021-04-09 16:48:59.548018", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Dimension-wise Accounts Balance Report", + "owner": "Administrator", + "prepared_report": 0, + "ref_doctype": "GL Entry", + "report_name": "Dimension-wise Accounts Balance Report", + "report_type": "Script Report", + "roles": [] +} \ No newline at end of file diff --git a/erpnext/accounts/report/dimension_wise_accounts_balance_report/dimension_wise_accounts_balance_report.py b/erpnext/accounts/report/dimension_wise_accounts_balance_report/dimension_wise_accounts_balance_report.py new file mode 100644 index 00000000000..9769a458dd6 --- /dev/null +++ b/erpnext/accounts/report/dimension_wise_accounts_balance_report/dimension_wise_accounts_balance_report.py @@ -0,0 +1,205 @@ +# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +import frappe, erpnext +from frappe import _ +from frappe.utils import (flt, getdate, get_first_day, add_months, add_days, formatdate, cstr, cint) + +from erpnext.accounts.report.financial_statements import get_accounts, filter_accounts, get_appropriate_currency, get_fiscal_year_data, validate_fiscal_year, filter_out_zero_value_rows +from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions, get_dimension_with_children +from erpnext.accounts.report.trial_balance.trial_balance import validate_filters, get_opening_balances, calculate_values + +from six import itervalues + +def execute(filters=None): + validate_filters(filters) + dimension_items_list = get_dimension_items_list(filters.dimension, filters.company) + + if not dimension_items_list: + return [], [] + + dimension_items_list = [''.join(d) for d in dimension_items_list] + columns = get_columns(dimension_items_list) + data = get_data(filters, dimension_items_list) + + return columns, data + +def get_data(filters, dimension_items_list): + company_currency = erpnext.get_company_currency(filters.company) + acc = frappe.db.sql(""" + select + name, account_number, parent_account, lft, rgt, root_type, + report_type, account_name, include_in_gross, account_type, is_group + from + `tabAccount` + where + company=%s + order by lft""", (filters.company), as_dict=True) + + if not acc: + return None + + accounts, accounts_by_name, parent_children_map = filter_accounts(acc) + + min_lft, max_rgt = frappe.db.sql("""select min(lft), max(rgt) from `tabAccount` + where company=%s""", (filters.company))[0] + + account = frappe.db.sql_list("""select name from `tabAccount` + where lft >= %s and rgt <= %s and company = %s""", (min_lft, max_rgt, filters.company)) + + gl_entries_by_account = {} + set_gl_entries_by_account(dimension_items_list, filters, account, gl_entries_by_account) + format_gl_entries(gl_entries_by_account, accounts_by_name, dimension_items_list) + accumulate_values_into_parents(accounts, accounts_by_name, dimension_items_list) + out = prepare_data(accounts, filters, parent_children_map, company_currency, dimension_items_list) + out = filter_out_zero_value_rows(out, parent_children_map) + + return out + +def set_gl_entries_by_account(dimension_items_list, filters, account, gl_entries_by_account): + for item in dimension_items_list: + condition = get_condition(filters.from_date, item, filters.dimension) + if account: + condition += " and account in ({})"\ + .format(", ".join([frappe.db.escape(d) for d in account])) + + gl_filters = { + "company": filters.get("company"), + "from_date": filters.get("from_date"), + "to_date": filters.get("to_date"), + "finance_book": cstr(filters.get("finance_book")) + } + + gl_filters['item'] = ''.join(item) + + if filters.get("include_default_book_entries"): + gl_filters["company_fb"] = frappe.db.get_value("Company", + filters.company, 'default_finance_book') + + for key, value in filters.items(): + if value: + gl_filters.update({ + key: value + }) + + gl_entries = frappe.db.sql(""" + select + posting_date, account, debit, credit, is_opening, fiscal_year, + debit_in_account_currency, credit_in_account_currency, account_currency + from + `tabGL Entry` + where + company=%(company)s + {condition} + and posting_date <= %(to_date)s + and is_cancelled = 0 + order by account, posting_date""".format( + condition=condition), + gl_filters, as_dict=True) #nosec + + for entry in gl_entries: + entry['dimension_item'] = ''.join(item) + gl_entries_by_account.setdefault(entry.account, []).append(entry) + +def format_gl_entries(gl_entries_by_account, accounts_by_name, dimension_items_list): + + for entries in itervalues(gl_entries_by_account): + for entry in entries: + d = accounts_by_name.get(entry.account) + if not d: + frappe.msgprint( + _("Could not retrieve information for {0}.").format(entry.account), title="Error", + raise_exception=1 + ) + for item in dimension_items_list: + if item == entry.dimension_item: + x = flt(entry.debit) - flt(entry.credit) + d[frappe.scrub(item)] = d.get(frappe.scrub(item), 0.0) + flt(entry.debit) - flt(entry.credit) + +def prepare_data(accounts, filters, parent_children_map, company_currency, dimension_items_list): + data = [] + + for d in accounts: + has_value = False + row = { + "account": d.name, + "parent_account": d.parent_account, + "indent": d.indent, + "from_date": filters.from_date, + "to_date": filters.to_date, + "currency": company_currency, + "account_name": ('{} - {}'.format(d.account_number, d.account_name) + if d.account_number else d.account_name) + } + + for item in dimension_items_list: + row[frappe.scrub(item)] = flt(d.get(frappe.scrub(item), 0.0), 3) + + if abs(row[frappe.scrub(item)]) >= 0.005: + # ignore zero values + has_value = True + + row["has_value"] = has_value + data.append(row) + + return data + +def accumulate_values_into_parents(accounts, accounts_by_name, dimension_items_list): + """accumulate children's values in parent accounts""" + for d in reversed(accounts): + if d.parent_account: + for item in dimension_items_list: + accounts_by_name[d.parent_account][frappe.scrub(item)] = \ + accounts_by_name[d.parent_account].get(frappe.scrub(item), 0.0) + d.get(frappe.scrub(item), 0.0) + +def get_condition(from_date, item, dimension): + conditions = [] + + if from_date: + conditions.append("posting_date >= %(from_date)s") + if dimension: + if dimension not in ['Cost Center', 'Project']: + if dimension in ['Customer', 'Supplier']: + dimension = 'Party' + else: + dimension = 'Voucher No' + txt = "{0} = %(item)s".format(frappe.scrub(dimension)) + conditions.append(txt) + + return " and {}".format(" and ".join(conditions)) if conditions else "" + +def get_dimension_items_list(dimension, company): + meta = frappe.get_meta(dimension, cached=False) + fieldnames = [d.fieldname for d in meta.get("fields")] + filters = {} + if 'company' in fieldnames: + filters['company'] = company + return frappe.get_all(dimension, filters, as_list=True) + +def get_columns(dimension_items_list, accumulated_values=1, company=None): + columns = [{ + "fieldname": "account", + "label": _("Account"), + "fieldtype": "Link", + "options": "Account", + "width": 300 + }] + if company: + columns.append({ + "fieldname": "currency", + "label": _("Currency"), + "fieldtype": "Link", + "options": "Currency", + "hidden": 1 + }) + for item in dimension_items_list: + columns.append({ + "fieldname": frappe.scrub(item), + "label": item, + "fieldtype": "Currency", + "options": "currency", + "width": 150 + }) + + return columns From c42318ec24fdecda9d5cdc0a8ca8f63e9be83a30 Mon Sep 17 00:00:00 2001 From: Afshan Date: Fri, 9 Apr 2021 17:44:30 +0530 Subject: [PATCH 002/135] chores: clean up --- .../dimension_wise_accounts_balance_report.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/erpnext/accounts/report/dimension_wise_accounts_balance_report/dimension_wise_accounts_balance_report.py b/erpnext/accounts/report/dimension_wise_accounts_balance_report/dimension_wise_accounts_balance_report.py index 9769a458dd6..7f38770a32a 100644 --- a/erpnext/accounts/report/dimension_wise_accounts_balance_report/dimension_wise_accounts_balance_report.py +++ b/erpnext/accounts/report/dimension_wise_accounts_balance_report/dimension_wise_accounts_balance_report.py @@ -4,11 +4,10 @@ from __future__ import unicode_literals import frappe, erpnext from frappe import _ -from frappe.utils import (flt, getdate, get_first_day, add_months, add_days, formatdate, cstr, cint) +from frappe.utils import (flt, cstr) -from erpnext.accounts.report.financial_statements import get_accounts, filter_accounts, get_appropriate_currency, get_fiscal_year_data, validate_fiscal_year, filter_out_zero_value_rows -from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions, get_dimension_with_children -from erpnext.accounts.report.trial_balance.trial_balance import validate_filters, get_opening_balances, calculate_values +from erpnext.accounts.report.financial_statements import filter_accounts, filter_out_zero_value_rows +from erpnext.accounts.report.trial_balance.trial_balance import validate_filters from six import itervalues @@ -114,7 +113,6 @@ def format_gl_entries(gl_entries_by_account, accounts_by_name, dimension_items_l ) for item in dimension_items_list: if item == entry.dimension_item: - x = flt(entry.debit) - flt(entry.credit) d[frappe.scrub(item)] = d.get(frappe.scrub(item), 0.0) + flt(entry.debit) - flt(entry.credit) def prepare_data(accounts, filters, parent_children_map, company_currency, dimension_items_list): From 6d3305c4461053a6d978beef379ca0f090fc10fa Mon Sep 17 00:00:00 2001 From: Afshan Date: Wed, 21 Apr 2021 15:34:58 +0530 Subject: [PATCH 003/135] fix: added total column --- .../dimension_wise_accounts_balance_report.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/erpnext/accounts/report/dimension_wise_accounts_balance_report/dimension_wise_accounts_balance_report.py b/erpnext/accounts/report/dimension_wise_accounts_balance_report/dimension_wise_accounts_balance_report.py index 7f38770a32a..de7ed4926e1 100644 --- a/erpnext/accounts/report/dimension_wise_accounts_balance_report/dimension_wise_accounts_balance_report.py +++ b/erpnext/accounts/report/dimension_wise_accounts_balance_report/dimension_wise_accounts_balance_report.py @@ -120,6 +120,7 @@ def prepare_data(accounts, filters, parent_children_map, company_currency, dimen for d in accounts: has_value = False + total = 0 row = { "account": d.name, "parent_account": d.parent_account, @@ -137,8 +138,10 @@ def prepare_data(accounts, filters, parent_children_map, company_currency, dimen if abs(row[frappe.scrub(item)]) >= 0.005: # ignore zero values has_value = True + total += flt(d.get(frappe.scrub(item), 0.0), 3) row["has_value"] = has_value + row["total"] = total data.append(row) return data @@ -199,5 +202,12 @@ def get_columns(dimension_items_list, accumulated_values=1, company=None): "options": "currency", "width": 150 }) + columns.append({ + "fieldname": "total", + "label": "Total", + "fieldtype": "Currency", + "options": "currency", + "width": 150 + }) return columns From 77154418422074e9c125d6f5505b7891746d7efe Mon Sep 17 00:00:00 2001 From: noahjacob Date: Sun, 9 May 2021 20:02:23 +0530 Subject: [PATCH 004/135] feat: added supplier item group doctype --- .../doctype/supplier_item_group/__init__.py | 0 .../supplier_item_group.js | 8 +++ .../supplier_item_group.json | 51 +++++++++++++++++++ .../supplier_item_group.py | 10 ++++ .../test_supplier_item_group.py | 10 ++++ 5 files changed, 79 insertions(+) create mode 100644 erpnext/buying/doctype/supplier_item_group/__init__.py create mode 100644 erpnext/buying/doctype/supplier_item_group/supplier_item_group.js create mode 100644 erpnext/buying/doctype/supplier_item_group/supplier_item_group.json create mode 100644 erpnext/buying/doctype/supplier_item_group/supplier_item_group.py create mode 100644 erpnext/buying/doctype/supplier_item_group/test_supplier_item_group.py diff --git a/erpnext/buying/doctype/supplier_item_group/__init__.py b/erpnext/buying/doctype/supplier_item_group/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/buying/doctype/supplier_item_group/supplier_item_group.js b/erpnext/buying/doctype/supplier_item_group/supplier_item_group.js new file mode 100644 index 00000000000..f7da90d98d6 --- /dev/null +++ b/erpnext/buying/doctype/supplier_item_group/supplier_item_group.js @@ -0,0 +1,8 @@ +// Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Supplier Item Group', { + // refresh: function(frm) { + + // } +}); diff --git a/erpnext/buying/doctype/supplier_item_group/supplier_item_group.json b/erpnext/buying/doctype/supplier_item_group/supplier_item_group.json new file mode 100644 index 00000000000..1417ec23cf3 --- /dev/null +++ b/erpnext/buying/doctype/supplier_item_group/supplier_item_group.json @@ -0,0 +1,51 @@ +{ + "actions": [], + "creation": "2021-05-07 18:16:40.621421", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "supplier", + "item_group" + ], + "fields": [ + { + "fieldname": "supplier", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Supplier", + "options": "Supplier" + }, + { + "fieldname": "item_group", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Item Group", + "options": "Item Group" + } + ], + "index_web_pages_for_search": 1, + "links": [], + "modified": "2021-05-07 18:16:40.621421", + "modified_by": "Administrator", + "module": "Buying", + "name": "Supplier Item Group", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, + "write": 1 + } + ], + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 +} \ No newline at end of file diff --git a/erpnext/buying/doctype/supplier_item_group/supplier_item_group.py b/erpnext/buying/doctype/supplier_item_group/supplier_item_group.py new file mode 100644 index 00000000000..6fbeb372429 --- /dev/null +++ b/erpnext/buying/doctype/supplier_item_group/supplier_item_group.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2021, 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 SupplierItemGroup(Document): + pass diff --git a/erpnext/buying/doctype/supplier_item_group/test_supplier_item_group.py b/erpnext/buying/doctype/supplier_item_group/test_supplier_item_group.py new file mode 100644 index 00000000000..c75044d44eb --- /dev/null +++ b/erpnext/buying/doctype/supplier_item_group/test_supplier_item_group.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt +from __future__ import unicode_literals + +# import frappe +import unittest + +class TestSupplierItemGroup(unittest.TestCase): + pass From a60c3081cf54b61757c1196c957bdbf3f5738a99 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Tue, 11 May 2021 16:38:33 +0530 Subject: [PATCH 005/135] fix: Breaking cost center validation --- erpnext/controllers/accounts_controller.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index c409850734c..996c4ed11ba 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -368,6 +368,11 @@ 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)) + # Double check for cost center + # Items add via promotional scheme may not have cost center set + if hasattr(item, 'cost_center') and not item.get('cost_center'): + item.set('cost_center', self.get('cost_center') or erpnext.get_default_cost_center(self.company)) + if ret.get("pricing_rules"): self.apply_pricing_rule_on_items(item, ret) self.set_pricing_rule_details(item, ret) From a665f14620b453db7b144f4f260fd47ed7d99682 Mon Sep 17 00:00:00 2001 From: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> Date: Tue, 11 May 2021 17:33:59 +0530 Subject: [PATCH 006/135] fix: Error on adding bank account to plaid (#25658) --- .../doctype/plaid_settings/plaid_settings.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py index 16c65733f0b..21f1db619e4 100644 --- a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py +++ b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py @@ -90,9 +90,9 @@ def add_bank_accounts(response, bank, company): "bank": bank["bank_name"], "account": default_gl_account.account, "account_name": account["name"], - "account_type": account["type"] or "", - "account_subtype": account["subtype"] or "", - "mask": account["mask"] or "", + "account_type": account.get("type", ""), + "account_subtype": account.get("subtype", ""), + "mask": account.get("mask", ""), "integration_id": account["id"], "is_company_account": 1, "company": company From b1f8c80be3a80a59f4389a5350411c0c4a4ca318 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Tue, 11 May 2021 18:27:20 +0530 Subject: [PATCH 007/135] ci: enable semgrep check on v13 branches and update rules (#25647) * ci: enable semgrep on v13 branches * ci: break semgrep steps for nicer output * ci: update semgrep rules inline with frappe repo --- .flake8 | 3 +- .../semgrep_rules/frappe_correctness.py | 64 ++++++++++--- .../semgrep_rules/frappe_correctness.yml | 89 ++++++++++++++++--- .github/helper/semgrep_rules/translate.js | 7 ++ .github/helper/semgrep_rules/translate.yml | 9 +- .github/workflows/semgrep.yml | 12 ++- 6 files changed, 150 insertions(+), 34 deletions(-) diff --git a/.flake8 b/.flake8 index 399b176e1d0..56c9b9a3699 100644 --- a/.flake8 +++ b/.flake8 @@ -29,4 +29,5 @@ ignore = B950, W191, -max-line-length = 200 \ No newline at end of file +max-line-length = 200 +exclude=.github/helper/semgrep_rules diff --git a/.github/helper/semgrep_rules/frappe_correctness.py b/.github/helper/semgrep_rules/frappe_correctness.py index 4798b927f83..745e6463b8a 100644 --- a/.github/helper/semgrep_rules/frappe_correctness.py +++ b/.github/helper/semgrep_rules/frappe_correctness.py @@ -4,25 +4,61 @@ from frappe import _, flt from frappe.model.document import Document +# ruleid: frappe-modifying-but-not-comitting def on_submit(self): if self.value_of_goods == 0: frappe.throw(_('Value of goods cannot be 0')) - # ruleid: frappe-modifying-after-submit self.status = 'Submitted' + +# ok: frappe-modifying-but-not-comitting def on_submit(self): - if flt(self.per_billed) < 100: - self.update_billing_status() - else: - # todook: frappe-modifying-after-submit - self.status = "Completed" - self.db_set("status", "Completed") + if self.value_of_goods == 0: + frappe.throw(_('Value of goods cannot be 0')) + self.status = 'Submitted' + self.db_set('status', 'Submitted') -class TestDoc(Document): - pass +# ok: frappe-modifying-but-not-comitting +def on_submit(self): + if self.value_of_goods == 0: + frappe.throw(_('Value of goods cannot be 0')) + x = "y" + self.status = x + self.db_set('status', x) - def validate(self): - #ruleid: frappe-modifying-child-tables-while-iterating - for item in self.child_table: - if item.value < 0: - self.remove(item) + +# ok: frappe-modifying-but-not-comitting +def on_submit(self): + x = "y" + self.status = x + self.save() + +# ruleid: frappe-modifying-but-not-comitting-other-method +class DoctypeClass(Document): + def on_submit(self): + self.good_method() + self.tainted_method() + + def tainted_method(self): + self.status = "uptate" + + +# ok: frappe-modifying-but-not-comitting-other-method +class DoctypeClass(Document): + def on_submit(self): + self.good_method() + self.tainted_method() + + def tainted_method(self): + self.status = "update" + self.db_set("status", "update") + +# ok: frappe-modifying-but-not-comitting-other-method +class DoctypeClass(Document): + def on_submit(self): + self.good_method() + self.tainted_method() + self.save() + + def tainted_method(self): + self.status = "uptate" diff --git a/.github/helper/semgrep_rules/frappe_correctness.yml b/.github/helper/semgrep_rules/frappe_correctness.yml index 54df0624806..faab3344a62 100644 --- a/.github/helper/semgrep_rules/frappe_correctness.yml +++ b/.github/helper/semgrep_rules/frappe_correctness.yml @@ -1,32 +1,93 @@ # This file specifies rules for correctness according to how frappe doctype data model works. rules: -- id: frappe-modifying-after-submit +- id: frappe-modifying-but-not-comitting patterns: - - pattern: self.$ATTR = ... - - pattern-inside: | - def on_submit(self, ...): + - pattern: | + def $METHOD(self, ...): ... + self.$ATTR = ... + - pattern-not: | + def $METHOD(self, ...): + ... + self.$ATTR = ... + ... + self.db_set(..., self.$ATTR, ...) + - pattern-not: | + def $METHOD(self, ...): + ... + self.$ATTR = $SOME_VAR + ... + self.db_set(..., $SOME_VAR, ...) + - pattern-not: | + def $METHOD(self, ...): + ... + self.$ATTR = $SOME_VAR + ... + self.save() - metavariable-regex: metavariable: '$ATTR' # this is negative look-ahead, add more attrs to ignore like (ignore|ignore_this_too|ignore_me) - regex: '^(?!status_updater)(.*)$' + regex: '^(?!ignore_linked_doctypes|status_updater)(.*)$' + - metavariable-regex: + metavariable: "$METHOD" + regex: "(on_submit|on_cancel)" message: | - Doctype modified after submission. Please check if modification of self.$ATTR is commited to database. + DocType modified in self.$METHOD. Please check if modification of self.$ATTR is commited to database. languages: [python] severity: ERROR -- id: frappe-modifying-after-cancel +- id: frappe-modifying-but-not-comitting-other-method patterns: - - pattern: self.$ATTR = ... - - pattern-inside: | - def on_cancel(self, ...): + - pattern: | + class $DOCTYPE(...): + def $METHOD(self, ...): ... - - metavariable-regex: - metavariable: '$ATTR' - regex: '^(?!ignore_linked_doctypes|status_updater)(.*)$' + self.$ANOTHER_METHOD() + ... + + def $ANOTHER_METHOD(self, ...): + ... + self.$ATTR = ... + - pattern-not: | + class $DOCTYPE(...): + def $METHOD(self, ...): + ... + self.$ANOTHER_METHOD() + ... + + def $ANOTHER_METHOD(self, ...): + ... + self.$ATTR = ... + ... + self.db_set(..., self.$ATTR, ...) + - pattern-not: | + class $DOCTYPE(...): + def $METHOD(self, ...): + ... + self.$ANOTHER_METHOD() + ... + + def $ANOTHER_METHOD(self, ...): + ... + self.$ATTR = $SOME_VAR + ... + self.db_set(..., $SOME_VAR, ...) + - pattern-not: | + class $DOCTYPE(...): + def $METHOD(self, ...): + ... + self.$ANOTHER_METHOD() + ... + self.save() + def $ANOTHER_METHOD(self, ...): + ... + self.$ATTR = ... + - metavariable-regex: + metavariable: "$METHOD" + regex: "(on_submit|on_cancel)" message: | - Doctype modified after cancellation. Please check if modification of self.$ATTR is commited to database. + self.$ANOTHER_METHOD is called from self.$METHOD, check if changes to self.$ATTR are commited to database. languages: [python] severity: ERROR diff --git a/.github/helper/semgrep_rules/translate.js b/.github/helper/semgrep_rules/translate.js index 7b92fe2dffb..9cdfb75d0be 100644 --- a/.github/helper/semgrep_rules/translate.js +++ b/.github/helper/semgrep_rules/translate.js @@ -35,3 +35,10 @@ __('You have' + 'subscribers in your mailing list.') // ruleid: frappe-translation-js-splitting __('You have {0} subscribers' + 'in your mailing list', [subscribers.length]) + +// ok: frappe-translation-js-splitting +__("Ctrl+Enter to add comment") + +// ruleid: frappe-translation-js-splitting +__('You have {0} subscribers \ + in your mailing list', [subscribers.length]) diff --git a/.github/helper/semgrep_rules/translate.yml b/.github/helper/semgrep_rules/translate.yml index 3737da5a7e2..fa4ec9e15d0 100644 --- a/.github/helper/semgrep_rules/translate.yml +++ b/.github/helper/semgrep_rules/translate.yml @@ -42,9 +42,10 @@ rules: - id: frappe-translation-python-splitting pattern-either: - - pattern: _(...) + ... + _(...) + - pattern: _(...) + _(...) - pattern: _("..." + "...") - - pattern-regex: '_\([^\)]*\\\s*' + - pattern-regex: '_\([^\)]*\\\s*' # lines broken by `\` + - pattern-regex: '_\(\s*\n' # line breaks allowed by python for using ( ) message: | Do not split strings inside translate function. Do not concatenate using translate functions. Please refer: https://frappeframework.com/docs/user/en/translations @@ -53,8 +54,8 @@ rules: - id: frappe-translation-js-splitting pattern-either: - - pattern-regex: '__\([^\)]*[\+\\]\s*' - - pattern: __('...' + '...') + - pattern-regex: '__\([^\)]*[\\]\s+' + - pattern: __('...' + '...', ...) - pattern: __('...') + __('...') message: | Do not split strings inside translate function. Do not concatenate using translate functions. diff --git a/.github/workflows/semgrep.yml b/.github/workflows/semgrep.yml index df082632365..389524e9684 100644 --- a/.github/workflows/semgrep.yml +++ b/.github/workflows/semgrep.yml @@ -4,6 +4,8 @@ on: pull_request: branches: - develop + - version-13-hotfix + - version-13-pre-release jobs: semgrep: name: Frappe Linter @@ -14,11 +16,19 @@ jobs: uses: actions/setup-python@v2 with: python-version: 3.8 - - name: Run semgrep + + - name: Setup semgrep run: | python -m pip install -q semgrep git fetch origin $GITHUB_BASE_REF:$GITHUB_BASE_REF -q + + - name: Semgrep errors + run: | files=$(git diff --name-only --diff-filter=d $GITHUB_BASE_REF) [[ -d .github/helper/semgrep_rules ]] && semgrep --severity ERROR --config=.github/helper/semgrep_rules --quiet --error $files semgrep --config="r/python.lang.correctness" --quiet --error $files + + - name: Semgrep warnings + run: | + files=$(git diff --name-only --diff-filter=d $GITHUB_BASE_REF) [[ -d .github/helper/semgrep_rules ]] && semgrep --severity WARNING --severity INFO --config=.github/helper/semgrep_rules --quiet $files From d984be0ccd892989f3b1135f29c3bf4b8288cf9a Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Wed, 12 May 2021 12:32:14 +0530 Subject: [PATCH 008/135] fix: don't map set warehouse from delivery note to purchase receipt --- erpnext/stock/doctype/delivery_note/delivery_note.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py index d326a041730..cce51cb9b17 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/delivery_note.py @@ -732,7 +732,8 @@ def make_inter_company_transaction(doctype, source_name, target_doc=None): "doctype": target_doctype, "postprocess": update_details, "field_no_map": [ - "taxes_and_charges" + "taxes_and_charges", + "set_warehouse" ] }, doctype +" Item": { From e7a2fdd81a0b054b19d4eebc39a91cf34975ddb9 Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Mohsin Rajan Date: Wed, 12 May 2021 13:02:32 +0530 Subject: [PATCH 009/135] fix: change links in workspace (#25674) --- .../workspace/accounting/accounting.json | 29 ++++--------------- 1 file changed, 5 insertions(+), 24 deletions(-) diff --git a/erpnext/accounts/workspace/accounting/accounting.json b/erpnext/accounts/workspace/accounting/accounting.json index 9ffa481c1cb..df68318052f 100644 --- a/erpnext/accounts/workspace/accounting/accounting.json +++ b/erpnext/accounts/workspace/accounting/accounting.json @@ -15,6 +15,7 @@ "hide_custom": 0, "icon": "accounting", "idx": 0, + "is_default": 0, "is_standard": 1, "label": "Accounting", "links": [ @@ -625,9 +626,9 @@ "dependencies": "", "hidden": 0, "is_query_report": 0, - "label": "Bank Reconciliation", - "link_to": "bank-reconciliation", - "link_type": "Page", + "label": "Bank Reconciliation Tool", + "link_to": "Bank Reconciliation Tool", + "link_type": "DocType", "onboard": 0, "type": "Link" }, @@ -641,26 +642,6 @@ "onboard": 0, "type": "Link" }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Bank Statement Transaction Entry", - "link_to": "Bank Statement Transaction Entry", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Bank Statement Settings", - "link_to": "Bank Statement Settings", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, { "hidden": 0, "is_query_report": 0, @@ -1071,7 +1052,7 @@ "type": "Link" } ], - "modified": "2021-03-04 00:38:35.349024", + "modified": "2021-05-12 11:48:01.905144", "modified_by": "Administrator", "module": "Accounts", "name": "Accounting", From 9f017a351ba58e4f47e2af78234962d4b002fb2d Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Wed, 12 May 2021 16:35:09 +0530 Subject: [PATCH 010/135] fix: updated modified time to pull new fields --- erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json index 24e67febca5..d3d3ffa17fa 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json @@ -1380,7 +1380,7 @@ "idx": 204, "is_submittable": 1, "links": [], - "modified": "2021-03-30 22:45:58.334107", + "modified": "2021-04-30 22:45:58.334107", "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Invoice", From dc205e805f5875dd2e74bea80f70a9910319b87e Mon Sep 17 00:00:00 2001 From: Afshan <33727827+AfshanKhan@users.noreply.github.com> Date: Wed, 12 May 2021 17:42:06 +0530 Subject: [PATCH 011/135] fix: Dialog variable assignment after definition in POS (#25681) --- erpnext/selling/page/point_of_sale/pos_controller.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/erpnext/selling/page/point_of_sale/pos_controller.js b/erpnext/selling/page/point_of_sale/pos_controller.js index 8e0a1e1c185..4f4f1b2240b 100644 --- a/erpnext/selling/page/point_of_sale/pos_controller.js +++ b/erpnext/selling/page/point_of_sale/pos_controller.js @@ -56,10 +56,6 @@ erpnext.PointOfSale.Controller = class { dialog.fields_dict.balance_details.grid.refresh(); }); } - const pos_profile_query = { - query: 'erpnext.accounts.doctype.pos_profile.pos_profile.pos_profile_query', - filters: { company: dialog.fields_dict.company.get_value() } - } const dialog = new frappe.ui.Dialog({ title: __('Create POS Opening Entry'), static: true, @@ -105,6 +101,10 @@ erpnext.PointOfSale.Controller = class { primary_action_label: __('Submit') }); dialog.show(); + const pos_profile_query = { + query: 'erpnext.accounts.doctype.pos_profile.pos_profile.pos_profile_query', + filters: { company: dialog.fields_dict.company.get_value() } + }; } async prepare_app_defaults(data) { From c3c54fe05819a040fd45411fab5308c0afb5a53b Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Wed, 12 May 2021 19:42:04 +0530 Subject: [PATCH 012/135] fix: Woocommerce order sync issue --- .../connectors/woocommerce_connection.py | 30 +++++++++---------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/erpnext/erpnext_integrations/connectors/woocommerce_connection.py b/erpnext/erpnext_integrations/connectors/woocommerce_connection.py index 6dedaa8c530..a505ee09d28 100644 --- a/erpnext/erpnext_integrations/connectors/woocommerce_connection.py +++ b/erpnext/erpnext_integrations/connectors/woocommerce_connection.py @@ -1,6 +1,7 @@ from __future__ import unicode_literals import frappe, base64, hashlib, hmac, json +from frappe.utils import cstr from frappe import _ def verify_request(): @@ -146,22 +147,19 @@ def rename_address(address, customer): def link_items(items_list, woocommerce_settings, sys_lang): for item_data in items_list: - item_woo_com_id = item_data.get("product_id") + item_woo_com_id = cstr(item_data.get("product_id")) - if frappe.get_value("Item", {"woocommerce_id": item_woo_com_id}): - #Edit Item - item = frappe.get_doc("Item", {"woocommerce_id": item_woo_com_id}) - else: + if not frappe.db.get_value("Item", {"woocommerce_id": item_woo_com_id}, 'name'): #Create Item item = frappe.new_doc("Item") + item.item_code = _("woocommerce - {0}", sys_lang).format(item_woo_com_id) + item.stock_uom = woocommerce_settings.uom or _("Nos", sys_lang) + item.item_group = _("WooCommerce Products", sys_lang) - item.item_name = item_data.get("name") - item.item_code = _("woocommerce - {0}", sys_lang).format(item_data.get("product_id")) - item.woocommerce_id = item_data.get("product_id") - item.item_group = _("WooCommerce Products", sys_lang) - item.stock_uom = woocommerce_settings.uom or _("Nos", sys_lang) - item.flags.ignore_mandatory = True - item.save() + item.item_name = item_data.get("name") + item.woocommerce_id = item_woo_com_id + item.flags.ignore_mandatory = True + item.save() def create_sales_order(order, woocommerce_settings, customer_name, sys_lang): new_sales_order = frappe.new_doc("Sales Order") @@ -194,12 +192,12 @@ def set_items_in_sales_order(new_sales_order, woocommerce_settings, order, sys_l for item in order.get("line_items"): woocomm_item_id = item.get("product_id") - found_item = frappe.get_doc("Item", {"woocommerce_id": woocomm_item_id}) + found_item = frappe.get_doc("Item", {"woocommerce_id": cstr(woocomm_item_id)}) ordered_items_tax = item.get("total_tax") - new_sales_order.append("items",{ - "item_code": found_item.item_code, + new_sales_order.append("items", { + "item_code": found_item.name, "item_name": found_item.item_name, "description": found_item.item_name, "delivery_date": new_sales_order.delivery_date, @@ -207,7 +205,7 @@ def set_items_in_sales_order(new_sales_order, woocommerce_settings, order, sys_l "qty": item.get("quantity"), "rate": item.get("price"), "warehouse": woocommerce_settings.warehouse or default_warehouse - }) + }) add_tax_details(new_sales_order, ordered_items_tax, "Ordered Item tax", woocommerce_settings.tax_account) From 0c482fde5f14a1454cd5aa6a6b28fec245bf72d6 Mon Sep 17 00:00:00 2001 From: Anurag Mishra <32095923+Anurag810@users.noreply.github.com> Date: Thu, 13 May 2021 13:20:14 +0530 Subject: [PATCH 013/135] feat: Leave Policy Assignment Refactor (#24327) * feat: Leave Policy Assignment Refactor * fix: Changes Requested * fix: sider * fix: changes requested * test: fixed * test: fixed wrong set query * fix: remove commented code * fix(style): extra space Co-authored-by: Rucha Mahabal --- erpnext/hooks.py | 2 - .../hr/doctype/employee/employee_dashboard.py | 16 +++--- .../hr/doctype/hr_settings/hr_settings.json | 9 +--- .../test_leave_application.py | 2 - .../leave_encashment/test_leave_encashment.py | 4 -- .../leave_policy/leave_policy_dashboard.py | 2 +- .../leave_policy_assignment.js | 43 ++++++---------- .../leave_policy_assignment.py | 49 +++++-------------- .../leave_policy_assignment_dashboard.py | 13 +++++ .../leave_policy_assignment_list.js | 32 +----------- .../test_leave_policy_assignment.py | 2 - erpnext/hr/utils.py | 7 --- 12 files changed, 53 insertions(+), 128 deletions(-) create mode 100644 erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment_dashboard.py diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 9d1ce9bbbfb..2a70f2bd39b 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -365,10 +365,8 @@ scheduler_events = { "erpnext.setup.doctype.email_digest.email_digest.send", "erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.update_latest_price_in_all_boms", "erpnext.hr.doctype.leave_ledger_entry.leave_ledger_entry.process_expired_allocation", - "erpnext.hr.doctype.leave_policy_assignment.leave_policy_assignment.automatically_allocate_leaves_based_on_leave_policy", "erpnext.hr.utils.generate_leave_encashment", "erpnext.hr.utils.allocate_earned_leaves", - "erpnext.hr.utils.grant_leaves_automatically", "erpnext.loan_management.doctype.process_loan_security_shortfall.process_loan_security_shortfall.create_process_loan_security_shortfall", "erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual.process_loan_interest_accrual_for_term_loans", "erpnext.crm.doctype.lead.lead.daily_open_lead" diff --git a/erpnext/hr/doctype/employee/employee_dashboard.py b/erpnext/hr/doctype/employee/employee_dashboard.py index 02033321648..285374d9f69 100644 --- a/erpnext/hr/doctype/employee/employee_dashboard.py +++ b/erpnext/hr/doctype/employee/employee_dashboard.py @@ -11,8 +11,12 @@ def get_data(): }, 'transactions': [ { - 'label': _('Leave and Attendance'), - 'items': ['Attendance', 'Attendance Request', 'Leave Application', 'Leave Allocation', 'Employee Checkin'] + 'label': _('Attendance'), + 'items': ['Attendance', 'Attendance Request', 'Employee Checkin'] + }, + { + 'label': _('Leave'), + 'items': ['Leave Application', 'Leave Allocation', 'Leave Policy Assignment'] }, { 'label': _('Lifecycle'), @@ -30,10 +34,6 @@ def get_data(): 'label': _('Benefit'), 'items': ['Employee Benefit Application', 'Employee Benefit Claim'] }, - { - 'label': _('Evaluation'), - 'items': ['Appraisal'] - }, { 'label': _('Payroll'), 'items': ['Salary Structure Assignment', 'Salary Slip', 'Additional Salary', 'Timesheet','Employee Incentive', 'Retention Bonus', 'Bank Account'] @@ -42,5 +42,9 @@ def get_data(): 'label': _('Training'), 'items': ['Training Event', 'Training Result', 'Training Feedback', 'Employee Skill Map'] }, + { + 'label': _('Evaluation'), + 'items': ['Appraisal'] + }, ] } diff --git a/erpnext/hr/doctype/hr_settings/hr_settings.json b/erpnext/hr/doctype/hr_settings/hr_settings.json index 3db6c239ef0..2396a8eee92 100644 --- a/erpnext/hr/doctype/hr_settings/hr_settings.json +++ b/erpnext/hr/doctype/hr_settings/hr_settings.json @@ -23,7 +23,6 @@ "show_leaves_of_all_department_members_in_calendar", "auto_leave_encashment", "restrict_backdated_leave_application", - "automatically_allocate_leaves_based_on_leave_policy", "hiring_settings", "check_vacancies" ], @@ -133,12 +132,6 @@ "label": "Role Allowed to Create Backdated Leave Application", "options": "Role" }, - { - "default": "0", - "fieldname": "automatically_allocate_leaves_based_on_leave_policy", - "fieldtype": "Check", - "label": "Automatically Allocate Leaves Based On Leave Policy" - }, { "default": "1", "fieldname": "send_leave_notification", @@ -155,7 +148,7 @@ "idx": 1, "issingle": 1, "links": [], - "modified": "2021-04-26 10:52:56.192773", + "modified": "2021-05-11 10:52:56.192773", "modified_by": "Administrator", "module": "HR", "name": "HR Settings", diff --git a/erpnext/hr/doctype/leave_application/test_leave_application.py b/erpnext/hr/doctype/leave_application/test_leave_application.py index a4a96b813ee..2832e2fad3b 100644 --- a/erpnext/hr/doctype/leave_application/test_leave_application.py +++ b/erpnext/hr/doctype/leave_application/test_leave_application.py @@ -446,8 +446,6 @@ class TestLeaveApplication(unittest.TestCase): leave_policy_assignments = create_assignment_for_multiple_employees([employee.name], frappe._dict(data)) - frappe.get_doc("Leave Policy Assignment", leave_policy_assignments[0]).grant_leave_alloc_for_employee() - from erpnext.hr.utils import allocate_earned_leaves i = 0 while(i<14): diff --git a/erpnext/hr/doctype/leave_encashment/test_leave_encashment.py b/erpnext/hr/doctype/leave_encashment/test_leave_encashment.py index e0ffa5dd41a..c1da8b47ffa 100644 --- a/erpnext/hr/doctype/leave_encashment/test_leave_encashment.py +++ b/erpnext/hr/doctype/leave_encashment/test_leave_encashment.py @@ -44,10 +44,6 @@ class TestLeaveEncashment(unittest.TestCase): salary_structure = make_salary_structure("Salary Structure for Encashment", "Monthly", self.employee, other_details={"leave_encashment_amount_per_day": 50}) - #grant Leaves - frappe.get_doc("Leave Policy Assignment", leave_policy_assignments[0]).grant_leave_alloc_for_employee() - - def tearDown(self): for dt in ["Leave Period", "Leave Allocation", "Leave Ledger Entry", "Additional Salary", "Leave Encashment", "Salary Structure", "Leave Policy"]: frappe.db.sql("delete from `tab%s`" % dt) diff --git a/erpnext/hr/doctype/leave_policy/leave_policy_dashboard.py b/erpnext/hr/doctype/leave_policy/leave_policy_dashboard.py index e0ec4be2dce..ff7f0422e03 100644 --- a/erpnext/hr/doctype/leave_policy/leave_policy_dashboard.py +++ b/erpnext/hr/doctype/leave_policy/leave_policy_dashboard.py @@ -7,7 +7,7 @@ def get_data(): 'transactions': [ { 'label': _('Leaves'), - 'items': ['Leave Allocation'] + 'items': ['Leave Policy Assignment', 'Leave Allocation'] }, ] } \ No newline at end of file diff --git a/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.js b/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.js index 7c32a0dde09..0aaf4cf616e 100644 --- a/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.js +++ b/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.js @@ -4,35 +4,22 @@ frappe.ui.form.on('Leave Policy Assignment', { onload: function(frm) { frm.ignore_doctypes_on_cancel_all = ["Leave Ledger Entry"]; - }, - refresh: function(frm) { - if (frm.doc.docstatus === 1 && frm.doc.leaves_allocated === 0) { - frm.add_custom_button(__("Grant Leave"), function() { - - frappe.call({ - doc: frm.doc, - method: "grant_leave_alloc_for_employee", - callback: function(r) { - let leave_allocations = r.message; - let msg = frm.events.get_success_message(leave_allocations); - frappe.msgprint(msg); - cur_frm.refresh(); - } - }); - }); - } - }, - - get_success_message: function(leave_allocations) { - let msg = __("Leaves has been granted successfully"); - msg += "
"; - msg += ""; - for (let key in leave_allocations) { - msg += ""; - } - msg += "
"+__('Leave Type')+""+__("Leave Allocation")+""+__("Leaves Granted")+"
"+key+""+leave_allocations[key]["name"]+""+leave_allocations[key]["leaves"]+"
"; - return msg; + frm.set_query('leave_policy', function() { + return { + filters: { + "docstatus": 1 + } + }; + }); + frm.set_query('leave_period', function() { + return { + filters: { + "is_active": 1, + "company": frm.doc.company + } + }; + }); }, assignment_based_on: function(frm) { diff --git a/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.py b/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.py index 462b81df1d5..d7cb1c88c92 100644 --- a/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.py +++ b/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.py @@ -17,6 +17,9 @@ class LeavePolicyAssignment(Document): self.validate_policy_assignment_overlap() self.set_dates() + def on_submit(self): + self.grant_leave_alloc_for_employee() + def set_dates(self): if self.assignment_based_on == "Leave Period": self.effective_from, self.effective_to = frappe.db.get_value("Leave Period", self.leave_period, ["from_date", "to_date"]) @@ -75,7 +78,7 @@ class LeavePolicyAssignment(Document): from_date=self.effective_from, to_date=self.effective_to, new_leaves_allocated=new_leaves_allocated, - leave_period=self.leave_period or None, + leave_period=self.leave_period if self.assignment_based_on == "Leave Policy" else '', leave_policy_assignment = self.name, leave_policy = self.leave_policy, carry_forward=carry_forward @@ -131,22 +134,6 @@ class LeavePolicyAssignment(Document): return new_leaves_allocated -@frappe.whitelist() -def grant_leave_for_multiple_employees(leave_policy_assignments): - leave_policy_assignments = json.loads(leave_policy_assignments) - not_granted = [] - for assignment in leave_policy_assignments: - try: - frappe.get_doc("Leave Policy Assignment", assignment).grant_leave_alloc_for_employee() - except Exception: - not_granted.append(assignment) - - if len(not_granted): - msg = _("Leave not Granted for Assignments:")+ bold(comma_and(not_granted)) + _(". Please Check documents") - else: - msg = _("Leave granted Successfully") - frappe.msgprint(msg) - @frappe.whitelist() def create_assignment_for_multiple_employees(employees, data): @@ -166,29 +153,18 @@ def create_assignment_for_multiple_employees(employees, data): assignment.effective_to = getdate(data.effective_to) or None assignment.leave_period = data.leave_period or None assignment.carry_forward = data.carry_forward - assignment.save() - assignment.submit() + try: + assignment.submit() + except frappe.exceptions.ValidationError: + continue + + frappe.db.commit() + docs_name.append(assignment.name) + return docs_name - -def automatically_allocate_leaves_based_on_leave_policy(): - today = getdate() - automatically_allocate_leaves_based_on_leave_policy = frappe.db.get_single_value( - 'HR Settings', 'automatically_allocate_leaves_based_on_leave_policy' - ) - - pending_assignments = frappe.get_list( - "Leave Policy Assignment", - filters = {"docstatus": 1, "leaves_allocated": 0, "effective_from": today} - ) - - if len(pending_assignments) and automatically_allocate_leaves_based_on_leave_policy: - for assignment in pending_assignments: - frappe.get_doc("Leave Policy Assignment", assignment.name).grant_leave_alloc_for_employee() - - def get_leave_type_details(): leave_type_details = frappe._dict() leave_types = frappe.get_all("Leave Type", @@ -197,4 +173,3 @@ def get_leave_type_details(): for d in leave_types: leave_type_details.setdefault(d.name, d) return leave_type_details - diff --git a/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment_dashboard.py b/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment_dashboard.py new file mode 100644 index 00000000000..4bb0535cf8c --- /dev/null +++ b/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment_dashboard.py @@ -0,0 +1,13 @@ +from __future__ import unicode_literals +from frappe import _ + +def get_data(): + return { + 'fieldname': 'leave_policy_assignment', + 'transactions': [ + { + 'label': _('Leaves'), + 'items': ['Leave Allocation'] + }, + ] + } \ No newline at end of file diff --git a/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment_list.js b/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment_list.js index 468f243885c..8fe4b8f8efa 100644 --- a/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment_list.js +++ b/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment_list.js @@ -6,6 +6,7 @@ frappe.listview_settings['Leave Policy Assignment'] = { doctype: "Employee", target: cur_list, setters: { + employee_name: '', company: '', department: '', }, @@ -92,37 +93,6 @@ frappe.listview_settings['Leave Policy Assignment'] = { } }); }); - - list_view.page.add_inner_button(__("Grant Leaves"), function () { - me.dialog = new frappe.ui.form.MultiSelectDialog({ - doctype: "Leave Policy Assignment", - target: cur_list, - setters: { - company: '', - employee: '', - }, - get_query() { - return { - filters: { - docstatus: ['=', 1], - leaves_allocated: ['=', 0] - } - }; - }, - add_filters_group: 1, - primary_action_label: "Grant Leaves", - action(leave_policy_assignments) { - frappe.call({ - method: 'erpnext.hr.doctype.leave_policy_assignment.leave_policy_assignment.grant_leave_for_multiple_employees', - async: false, - args: { - leave_policy_assignments: leave_policy_assignments - } - }); - me.dialog.hide(); - } - }); - }); }, set_effective_date: function () { diff --git a/erpnext/hr/doctype/leave_policy_assignment/test_leave_policy_assignment.py b/erpnext/hr/doctype/leave_policy_assignment/test_leave_policy_assignment.py index 838e794795f..9a14e3588d0 100644 --- a/erpnext/hr/doctype/leave_policy_assignment/test_leave_policy_assignment.py +++ b/erpnext/hr/doctype/leave_policy_assignment/test_leave_policy_assignment.py @@ -35,7 +35,6 @@ class TestLeavePolicyAssignment(unittest.TestCase): leave_policy_assignments = create_assignment_for_multiple_employees([employee.name], frappe._dict(data)) leave_policy_assignment_doc = frappe.get_doc("Leave Policy Assignment", leave_policy_assignments[0]) - leave_policy_assignment_doc.grant_leave_alloc_for_employee() leave_policy_assignment_doc.reload() self.assertEqual(leave_policy_assignment_doc.leaves_allocated, 1) @@ -73,7 +72,6 @@ class TestLeavePolicyAssignment(unittest.TestCase): leave_policy_assignments = create_assignment_for_multiple_employees([employee.name], frappe._dict(data)) leave_policy_assignment_doc = frappe.get_doc("Leave Policy Assignment", leave_policy_assignments[0]) - leave_policy_assignment_doc.grant_leave_alloc_for_employee() leave_policy_assignment_doc.reload() diff --git a/erpnext/hr/utils.py b/erpnext/hr/utils.py index 2540b3db63b..80189e87b7a 100644 --- a/erpnext/hr/utils.py +++ b/erpnext/hr/utils.py @@ -500,13 +500,6 @@ def get_previous_claimed_amount(employee, payroll_period, non_pro_rata=False, co total_claimed_amount = sum_of_claimed_amount[0].total_amount return total_claimed_amount -def grant_leaves_automatically(): - automatically_allocate_leaves_based_on_leave_policy = frappe.db.get_singles_value("HR Settings", "automatically_allocate_leaves_based_on_leave_policy") - if automatically_allocate_leaves_based_on_leave_policy: - lpa = frappe.db.get_all("Leave Policy Assignment", filters={"effective_from": getdate(), "docstatus": 1, "leaves_allocated":0}) - for assignment in lpa: - frappe.get_doc("Leave Policy Assignment", assignment.name).grant_leave_alloc_for_employee() - def share_doc_with_approver(doc, user): # if approver does not have permissions, share if not frappe.has_permission(doc=doc, ptype="submit", user=user): From 95e05fbdac1398c0818e78d37aa93b90054ac346 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Thu, 13 May 2021 14:59:28 +0530 Subject: [PATCH 014/135] fix: Parameter for get_filtered_list_for_consolidated_report in consolidated balance sheet --- erpnext/accounts/report/balance_sheet/balance_sheet.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/report/balance_sheet/balance_sheet.py b/erpnext/accounts/report/balance_sheet/balance_sheet.py index 287b8a7484f..26bb44f4f7b 100644 --- a/erpnext/accounts/report/balance_sheet/balance_sheet.py +++ b/erpnext/accounts/report/balance_sheet/balance_sheet.py @@ -135,7 +135,7 @@ def get_report_summary(period_list, asset, liability, equity, provisional_profit # from consolidated financial statement if filters.get('accumulated_in_group_company'): - period_list = get_filtered_list_for_consolidated_report(period_list) + period_list = get_filtered_list_for_consolidated_report(filters, period_list) for period in period_list: key = period if consolidated else period.key From 27f50d5852d9f2525488193ce694b101b011966e Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Thu, 13 May 2021 01:37:12 +0530 Subject: [PATCH 015/135] fix: timeout error while loading warehouse tree --- erpnext/stock/doctype/warehouse/warehouse.py | 46 ++++++++++++++++--- .../stock/doctype/warehouse/warehouse_tree.js | 2 +- 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/erpnext/stock/doctype/warehouse/warehouse.py b/erpnext/stock/doctype/warehouse/warehouse.py index 6c84f168fd4..2062bddc7c9 100644 --- a/erpnext/stock/doctype/warehouse/warehouse.py +++ b/erpnext/stock/doctype/warehouse/warehouse.py @@ -3,8 +3,9 @@ from __future__ import unicode_literals import frappe, erpnext -from frappe.utils import cint, nowdate +from frappe.utils import cint, flt from frappe import throw, _ +from collections import defaultdict from frappe.utils.nestedset import NestedSet from erpnext.stock import get_warehouse_account from frappe.contacts.address_and_contact import load_address_and_contact @@ -139,8 +140,6 @@ class Warehouse(NestedSet): @frappe.whitelist() def get_children(doctype, parent=None, company=None, is_root=False): - from erpnext.stock.utils import get_stock_value_from_bin - if is_root: parent = "" @@ -153,13 +152,48 @@ def get_children(doctype, parent=None, company=None, is_root=False): warehouses = frappe.get_list(doctype, fields=fields, filters=filters, order_by='name') + company_currency = '' + if company: + company_currency = frappe.get_cached_value('Company', company, 'default_currency') + + warehouse_wise_value = get_warehouse_wise_stock_value(company) + # return warehouses for wh in warehouses: - wh["balance"] = get_stock_value_from_bin(warehouse=wh.value) - if company: - wh["company_currency"] = frappe.db.get_value('Company', company, 'default_currency') + wh["balance"] = warehouse_wise_value.get(wh.value) + if company_currency: + wh["company_currency"] = company_currency return warehouses +def get_warehouse_wise_stock_value(company): + warehouses = frappe.get_all('Warehouse', + fields = ['name', 'parent_warehouse'], filters = {'company': company}) + parent_warehouse = {d.name : d.parent_warehouse for d in warehouses} + + filters = {'warehouse': ('in', [data.name for data in warehouses])} + bin_data = frappe.get_all('Bin', fields = ['sum(stock_value) as stock_value', 'warehouse'], + filters = filters, group_by = 'warehouse') + + warehouse_wise_stock_value = defaultdict(float) + for row in bin_data: + if not row.stock_value: + continue + + warehouse_wise_stock_value[row.warehouse] = row.stock_value + update_value_in_parent_warehouse(warehouse_wise_stock_value, + parent_warehouse, row.warehouse, row.stock_value) + + return warehouse_wise_stock_value + +def update_value_in_parent_warehouse(warehouse_wise_stock_value, parent_warehouse_dict, warehouse, stock_value): + parent_warehouse = parent_warehouse_dict.get(warehouse) + if not parent_warehouse: + return + + warehouse_wise_stock_value[parent_warehouse] += flt(stock_value) + update_value_in_parent_warehouse(warehouse_wise_stock_value, parent_warehouse_dict, + parent_warehouse, stock_value) + @frappe.whitelist() def add_node(): from frappe.desk.treeview import make_tree_args diff --git a/erpnext/stock/doctype/warehouse/warehouse_tree.js b/erpnext/stock/doctype/warehouse/warehouse_tree.js index 3665c0530f2..407d7d1ccd5 100644 --- a/erpnext/stock/doctype/warehouse/warehouse_tree.js +++ b/erpnext/stock/doctype/warehouse/warehouse_tree.js @@ -20,7 +20,7 @@ frappe.treeview_settings['Warehouse'] = { onrender: function(node) { if (node.data && node.data.balance!==undefined) { $('' - + format_currency(Math.abs(node.data.balance), node.data.company_currency) + + format_currency((node.data.balance), node.data.company_currency) + '').insertBefore(node.$ul); } } From e85770fe3f7d64380b84d5c5b82412045459e5fe Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Mohsin Rajan Date: Thu, 13 May 2021 17:33:18 +0530 Subject: [PATCH 016/135] fix: bank statement import via google sheet (#25676) * fix: google sheet bank statement import * fix: quotes Co-authored-by: Ankush Menat * chore: add translation Co-authored-by: Ankush Menat * chore: grammar Co-authored-by: Ankush Menat * fix: remove comment Co-authored-by: Ankush Menat --- .../bank_statement_import.js | 1 + .../bank_statement_import.json | 6 +++--- .../bank_statement_import.py | 18 ++++++++++++++---- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.js b/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.js index 3dbd6053441..016f29a7b51 100644 --- a/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.js +++ b/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.js @@ -239,6 +239,7 @@ frappe.ui.form.on("Bank Statement Import", { "withdrawal", "description", "reference_number", + "bank_account" ], }, }); diff --git a/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.json b/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.json index 5e913cc2aac..7ffff02850c 100644 --- a/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.json +++ b/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.json @@ -146,7 +146,7 @@ }, { "depends_on": "eval:!doc.__islocal && !doc.import_file\n", - "description": "Must be a publicly accessible Google Sheets URL", + "description": "Must be a publicly accessible Google Sheets URL and adding Bank Account column is necessary for importing via Google Sheets", "fieldname": "google_sheets_url", "fieldtype": "Data", "label": "Import from Google Sheets" @@ -202,7 +202,7 @@ ], "hide_toolbar": 1, "links": [], - "modified": "2021-02-10 19:29:59.027325", + "modified": "2021-05-12 14:17:37.777246", "modified_by": "Administrator", "module": "Accounts", "name": "Bank Statement Import", @@ -224,4 +224,4 @@ "sort_field": "modified", "sort_order": "DESC", "track_changes": 1 -} \ No newline at end of file +} diff --git a/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.py b/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.py index 9f41b13f4b6..5f110e2727c 100644 --- a/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.py +++ b/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.py @@ -47,6 +47,13 @@ class BankStatementImport(DataImport): def start_import(self): + preview = frappe.get_doc("Bank Statement Import", self.name).get_preview_from_template( + self.import_file, self.google_sheets_url + ) + + if 'Bank Account' not in json.dumps(preview): + frappe.throw(_("Please add the Bank Account column")) + from frappe.core.page.background_jobs.background_jobs import get_info from frappe.utils.scheduler import is_scheduler_inactive @@ -67,6 +74,7 @@ class BankStatementImport(DataImport): data_import=self.name, bank_account=self.bank_account, import_file_path=self.import_file, + google_sheets_url=self.google_sheets_url, bank=self.bank, template_options=self.template_options, now=frappe.conf.developer_mode or frappe.flags.in_test, @@ -90,18 +98,20 @@ def download_errored_template(data_import_name): data_import = frappe.get_doc("Bank Statement Import", data_import_name) data_import.export_errored_rows() -def start_import(data_import, bank_account, import_file_path, bank, template_options): +def start_import(data_import, bank_account, import_file_path, google_sheets_url, bank, template_options): """This method runs in background job""" update_mapping_db(bank, template_options) data_import = frappe.get_doc("Bank Statement Import", data_import) + file = import_file_path if import_file_path else google_sheets_url - import_file = ImportFile("Bank Transaction", file = import_file_path, import_type="Insert New Records") + import_file = ImportFile("Bank Transaction", file = file, import_type="Insert New Records") data = import_file.raw_data - add_bank_account(data, bank_account) - write_files(import_file, data) + if import_file_path: + add_bank_account(data, bank_account) + write_files(import_file, data) try: i = Importer(data_import.reference_doctype, data_import=data_import) From af1376c1dfa501b5f93d06788ffe08a86116a33a Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Thu, 13 May 2021 17:39:49 +0530 Subject: [PATCH 017/135] chore: change today to now to get data for reposting --- .../doctype/repost_item_valuation/repost_item_valuation.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py index 3f837805695..0971d6fdb9b 100644 --- a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py +++ b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals import frappe, erpnext from frappe.model.document import Document -from frappe.utils import cint, get_link_to_form, add_to_date, today +from frappe.utils import cint, get_link_to_form, add_to_date, now from erpnext.stock.stock_ledger import repost_future_sle from erpnext.accounts.utils import update_gl_entries_after, check_if_stock_and_account_balance_synced from frappe.utils.user import get_users_with_role @@ -127,7 +127,7 @@ def repost_entries(): check_if_stock_and_account_balance_synced(today(), d.name) def get_repost_item_valuation_entries(): - date = add_to_date(today(), hours=-3) + date = add_to_date(now(), hours=-3) return frappe.db.sql(""" SELECT name from `tabRepost Item Valuation` WHERE status != 'Completed' and creation <= %s and docstatus = 1 From fc44478810e40bae8bb2a3e3d17978b87344a4ce Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Thu, 13 May 2021 17:42:33 +0530 Subject: [PATCH 018/135] Update repost_item_valuation.py --- .../doctype/repost_item_valuation/repost_item_valuation.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py index 0971d6fdb9b..27b8729ea05 100644 --- a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py +++ b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals import frappe, erpnext from frappe.model.document import Document -from frappe.utils import cint, get_link_to_form, add_to_date, now +from frappe.utils import cint, get_link_to_form, add_to_date, now, today from erpnext.stock.stock_ledger import repost_future_sle from erpnext.accounts.utils import update_gl_entries_after, check_if_stock_and_account_balance_synced from frappe.utils.user import get_users_with_role @@ -132,4 +132,4 @@ def get_repost_item_valuation_entries(): return frappe.db.sql(""" SELECT name from `tabRepost Item Valuation` WHERE status != 'Completed' and creation <= %s and docstatus = 1 ORDER BY timestamp(posting_date, posting_time) asc, creation asc - """, date, as_dict=1) \ No newline at end of file + """, date, as_dict=1) From 55fe85d850ca7db434177d3dd540a590c6f05b5e Mon Sep 17 00:00:00 2001 From: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> Date: Fri, 14 May 2021 12:17:41 +0530 Subject: [PATCH 019/135] feat(India): Multiple GST enhancement and fixes (#25249) * fix: RCM tax calculation * feat(India): ITC Reversal via Journal Entry * fix: Reverse Charge booking logic and validation * fix: Addd patch for availed ITC fields * fix: Hooks method to update availed ITC field * fix: Cleanup and fixes in GSTR3B report * fix: Update params in GSTR-1 report * fix: Debit note using Sales Invoice * fix: Setup and patch * fix: GSTR 3B report cleanup and updates * fix: Add method to get invoices liable to reverse charge * fix: Add taxable value in Purchase Invoice Item * fix: Inward supplies liable to reverse charge * fix: Linting issues * fix: GSTR3B report test --- .../doctype/gst_account/gst_account.json | 260 ++------ .../doctype/sales_invoice/sales_invoice.js | 14 + .../doctype/sales_invoice/sales_invoice.json | 13 +- erpnext/hooks.py | 9 +- erpnext/patches.txt | 1 + .../create_itc_reversal_custom_fields.py | 115 ++++ .../gstr_3b_report/gstr_3b_report.html | 2 +- .../doctype/gstr_3b_report/gstr_3b_report.py | 621 ++++++++---------- .../gstr_3b_report_template.json | 127 ++++ .../gstr_3b_report/test_gstr_3b_report.py | 3 +- erpnext/regional/india/setup.py | 44 +- erpnext/regional/india/utils.py | 146 ++-- erpnext/regional/report/gstr_1/gstr_1.js | 8 +- erpnext/regional/report/gstr_1/gstr_1.py | 106 ++- 14 files changed, 809 insertions(+), 660 deletions(-) create mode 100644 erpnext/patches/v12_0/create_itc_reversal_custom_fields.py create mode 100644 erpnext/regional/doctype/gstr_3b_report/gstr_3b_report_template.json diff --git a/erpnext/accounts/doctype/gst_account/gst_account.json b/erpnext/accounts/doctype/gst_account/gst_account.json index 70673387fe8..b6ec8844e18 100644 --- a/erpnext/accounts/doctype/gst_account/gst_account.json +++ b/erpnext/accounts/doctype/gst_account/gst_account.json @@ -1,196 +1,82 @@ { - "allow_copy": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "beta": 0, - "creation": "2018-01-02 15:48:58.768352", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 1, - "engine": "InnoDB", + "actions": [], + "creation": "2018-01-02 15:48:58.768352", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "company", + "cgst_account", + "sgst_account", + "igst_account", + "cess_account", + "is_reverse_charge_account" + ], "fields": [ { - "allow_bulk_edit": 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": 1, - "in_standard_filter": 0, - "label": "Company", - "length": 0, - "no_copy": 0, - "options": "Company", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, + "columns": 1, + "fieldname": "company", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Company", + "options": "Company", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "cgst_account", - "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": "CGST Account", - "length": 0, - "no_copy": 0, - "options": "Account", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, + "columns": 2, + "fieldname": "cgst_account", + "fieldtype": "Link", + "in_list_view": 1, + "label": "CGST Account", + "options": "Account", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "sgst_account", - "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": "SGST Account", - "length": 0, - "no_copy": 0, - "options": "Account", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, + "columns": 2, + "fieldname": "sgst_account", + "fieldtype": "Link", + "in_list_view": 1, + "label": "SGST Account", + "options": "Account", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "igst_account", - "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": "IGST Account", - "length": 0, - "no_copy": 0, - "options": "Account", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, + "columns": 2, + "fieldname": "igst_account", + "fieldtype": "Link", + "in_list_view": 1, + "label": "IGST Account", + "options": "Account", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "cess_account", - "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": "CESS Account", - "length": 0, - "no_copy": 0, - "options": "Account", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 + "columns": 2, + "fieldname": "cess_account", + "fieldtype": "Link", + "in_list_view": 1, + "label": "CESS Account", + "options": "Account" + }, + { + "columns": 1, + "default": "0", + "fieldname": "is_reverse_charge_account", + "fieldtype": "Check", + "in_list_view": 1, + "label": "Is Reverse Charge Account" } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 1, - "max_attachments": 0, - "modified": "2018-01-02 15:52:22.335988", - "modified_by": "Administrator", - "module": "Accounts", - "name": "GST Account", - "name_case": "", - "owner": "Administrator", - "permissions": [], - "quick_entry": 1, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 1, - "track_seen": 0 + ], + "index_web_pages_for_search": 1, + "istable": 1, + "links": [], + "modified": "2021-04-09 12:30:25.889993", + "modified_by": "Administrator", + "module": "Accounts", + "name": "GST Account", + "owner": "Administrator", + "permissions": [], + "quick_entry": 1, + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 } \ No newline at end of file diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js index 7c73ad6c90e..5538568de49 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js @@ -582,6 +582,16 @@ frappe.ui.form.on('Sales Invoice', { }; }); + frm.set_query("adjustment_against", function() { + return { + filters: { + company: frm.doc.company, + customer: frm.doc.customer, + docstatus: 1 + } + }; + }); + frm.custom_make_buttons = { 'Delivery Note': 'Delivery', 'Sales Invoice': 'Return / Credit Note', @@ -867,6 +877,10 @@ frappe.ui.form.on('Sales Invoice', { }) } + if (frm.doc.is_debit_note) { + frm.set_df_property('return_against', 'label', 'Adjustment Against'); + } + if (frappe.boot.active_domains.includes("Healthcare")) { frm.set_df_property("patient", "hidden", 0); frm.set_df_property("patient_name", "hidden", 0); diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json index c6c67b4ddc1..7ae20892d2a 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json @@ -16,6 +16,7 @@ "is_pos", "is_consolidated", "is_return", + "is_debit_note", "update_billed_amount_in_sales_order", "column_break1", "company", @@ -392,7 +393,7 @@ "read_only": 1 }, { - "depends_on": "return_against", + "depends_on": "eval:doc.return_against || doc.is_debit_note", "fieldname": "return_against", "fieldtype": "Link", "hide_days": 1, @@ -401,7 +402,7 @@ "no_copy": 1, "options": "Sales Invoice", "print_hide": 1, - "read_only": 1, + "read_only_depends_on": "eval:doc.is_return", "search_index": 1 }, { @@ -1953,6 +1954,12 @@ }, { "default": "0", + "fieldname": "is_debit_note", + "fieldtype": "Check", + "label": "Is Debit Note" + }, + { + "default": 0, "depends_on": "grand_total", "fieldname": "disable_rounded_total", "fieldtype": "Check", @@ -1969,7 +1976,7 @@ "link_fieldname": "consolidated_invoice" } ], - "modified": "2021-04-15 23:57:58.766651", + "modified": "2021-04-23 22:36:32.916354", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice", diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 2a70f2bd39b..55169dffbad 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -268,10 +268,12 @@ doc_events = { }, "Purchase Invoice": { "validate": [ - "erpnext.regional.india.utils.update_grand_total_for_rcm", + "erpnext.regional.india.utils.validate_reverse_charge_transaction", + "erpnext.regional.india.utils.update_itc_availed_fields", "erpnext.regional.united_arab_emirates.utils.update_grand_total_for_rcm", - "erpnext.regional.united_arab_emirates.utils.validate_returns" - ] + "erpnext.regional.united_arab_emirates.utils.validate_returns", + "erpnext.regional.india.utils.update_taxable_values" + ] }, "Payment Entry": { "on_submit": ["erpnext.regional.create_transaction_log", "erpnext.accounts.doctype.payment_request.payment_request.update_payment_req_status", "erpnext.accounts.doctype.dunning.dunning.resolve_dunning"], @@ -423,7 +425,6 @@ regional_overrides = { 'erpnext.controllers.taxes_and_totals.get_regional_round_off_accounts': 'erpnext.regional.india.utils.get_regional_round_off_accounts', 'erpnext.hr.utils.calculate_annual_eligible_hra_exemption': 'erpnext.regional.india.utils.calculate_annual_eligible_hra_exemption', 'erpnext.hr.utils.calculate_hra_exemption_for_period': 'erpnext.regional.india.utils.calculate_hra_exemption_for_period', - 'erpnext.accounts.doctype.purchase_invoice.purchase_invoice.make_regional_gl_entries': 'erpnext.regional.india.utils.make_regional_gl_entries', 'erpnext.controllers.accounts_controller.validate_einvoice_fields': 'erpnext.regional.india.e_invoice.utils.validate_einvoice_fields', 'erpnext.assets.doctype.asset.asset.get_depreciation_amount': 'erpnext.regional.india.utils.get_depreciation_amount' }, diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 82d223cada0..9b3ddd09e86 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -769,6 +769,7 @@ erpnext.patches.v13_0.rename_discharge_date_in_ip_record erpnext.patches.v12_0.create_taxable_value_field erpnext.patches.v12_0.add_gst_category_in_delivery_note erpnext.patches.v12_0.purchase_receipt_status +erpnext.patches.v12_0.create_itc_reversal_custom_fields erpnext.patches.v13_0.fix_non_unique_represents_company erpnext.patches.v12_0.add_document_type_field_for_italy_einvoicing erpnext.patches.v13_0.make_non_standard_user_type #13-04-2021 diff --git a/erpnext/patches/v12_0/create_itc_reversal_custom_fields.py b/erpnext/patches/v12_0/create_itc_reversal_custom_fields.py new file mode 100644 index 00000000000..0078a53cd69 --- /dev/null +++ b/erpnext/patches/v12_0/create_itc_reversal_custom_fields.py @@ -0,0 +1,115 @@ +from __future__ import unicode_literals +import frappe +from frappe.custom.doctype.custom_field.custom_field import create_custom_fields +from frappe.custom.doctype.property_setter.property_setter import make_property_setter +from erpnext.regional.india.utils import get_gst_accounts + +def execute(): + company = frappe.get_all('Company', filters = {'country': 'India'}, fields=['name']) + if not company: + return + + frappe.reload_doc("regional", "doctype", "gst_settings") + frappe.reload_doc("accounts", "doctype", "gst_account") + + journal_entry_types = frappe.get_meta("Journal Entry").get_options("voucher_type").split("\n") + ['Reversal Of ITC'] + make_property_setter('Journal Entry', 'voucher_type', 'options', '\n'.join(journal_entry_types), '') + + custom_fields = { + 'Journal Entry': [ + dict(fieldname='reversal_type', label='Reversal Type', + fieldtype='Select', insert_after='voucher_type', print_hide=1, + options="As per rules 42 & 43 of CGST Rules\nOthers", + depends_on="eval:doc.voucher_type=='Reversal Of ITC'", + mandatory_depends_on="eval:doc.voucher_type=='Reversal Of ITC'"), + dict(fieldname='company_address', label='Company Address', + fieldtype='Link', options='Address', insert_after='reversal_type', + print_hide=1, depends_on="eval:doc.voucher_type=='Reversal Of ITC'", + mandatory_depends_on="eval:doc.voucher_type=='Reversal Of ITC'"), + dict(fieldname='company_gstin', label='Company GSTIN', + fieldtype='Data', read_only=1, insert_after='company_address', print_hide=1, + fetch_from='company_address.gstin', + depends_on="eval:doc.voucher_type=='Reversal Of ITC'", + mandatory_depends_on="eval:doc.voucher_type=='Reversal Of ITC'") + ], + 'Purchase Invoice': [ + dict(fieldname='eligibility_for_itc', label='Eligibility For ITC', + fieldtype='Select', insert_after='reason_for_issuing_document', print_hide=1, + options='Input Service Distributor\nImport Of Service\nImport Of Capital Goods\nITC on Reverse Charge\nIneligible As Per Section 17(5)\nIneligible Others\nAll Other ITC', + default="All Other ITC") + ], + 'Purchase Invoice Item': [ + dict(fieldname='taxable_value', label='Taxable Value', + fieldtype='Currency', insert_after='base_net_amount', hidden=1, options="Company:company:default_currency", + print_hide=1) + ] + } + + create_custom_fields(custom_fields, update=True) + + # Patch ITC Availed fields from Data to Currency + # Patch Availed ITC for current fiscal_year + + gst_accounts = get_gst_accounts(only_non_reverse_charge=1) + + frappe.db.sql(""" + UPDATE `tabCustom Field` SET fieldtype='Currency', options='Company:company:default_currency' + WHERE dt = 'Purchase Invoice' and fieldname in ('itc_integrated_tax', 'itc_state_tax', 'itc_central_tax', + 'itc_cess_amount') + """) + + frappe.db.sql("""UPDATE `tabPurchase Invoice` set itc_integrated_tax = '0' + WHERE trim(coalesce(itc_integrated_tax, '')) = '' """) + + frappe.db.sql("""UPDATE `tabPurchase Invoice` set itc_state_tax = '0' + WHERE trim(coalesce(itc_state_tax, '')) = '' """) + + frappe.db.sql("""UPDATE `tabPurchase Invoice` set itc_central_tax = '0' + WHERE trim(coalesce(itc_central_tax, '')) = '' """) + + frappe.db.sql("""UPDATE `tabPurchase Invoice` set itc_cess_amount = '0' + WHERE trim(coalesce(itc_cess_amount, '')) = '' """) + + # Get purchase invoices + invoices = frappe.get_all('Purchase Invoice', + {'posting_date': ('>=', '2021-04-01'), 'eligibility_for_itc': ('!=', 'Ineligible')}, + ['name']) + + amount_map = {} + + if invoices: + invoice_list = set([d.name for d in invoices]) + + # Get GST applied + amounts = frappe.db.sql(""" + SELECT parent, account_head, sum(base_tax_amount_after_discount_amount) as amount + FROM `tabPurchase Taxes and Charges` + where parent in %s + GROUP BY parent, account_head + """, (invoice_list), as_dict=1) + + for d in amounts: + amount_map.setdefault(d.parent, + { + 'itc_integrated_tax': 0, + 'itc_state_tax': 0, + 'itc_central_tax': 0, + 'itc_cess_amount': 0 + }) + + if d.account_head in gst_accounts.get('igst_account'): + amount_map[d.parent]['itc_integrated_tax'] += d.amount + if d.account_head in gst_accounts.get('cgst_account'): + amount_map[d.parent]['itc_central_tax'] += d.amount + if d.account_head in gst_accounts.get('sgst_account'): + amount_map[d.parent]['itc_state_tax'] += d.amount + if d.account_head in gst_accounts.get('cess_account'): + amount_map[d.parent]['itc_cess_amount'] += d.amount + + for invoice, values in amount_map.items(): + frappe.db.set_value('Purchase Invoice', invoice, { + 'itc_integrated_tax': values.get('itc_integrated_tax'), + 'itc_central_tax': values.get('itc_central_tax'), + 'itc_state_tax': values['itc_state_tax'], + 'itc_cess_amount': values['itc_cess_amount'], + }) \ No newline at end of file diff --git a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.html b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.html index 369a4001ef6..3b6a45a3b42 100644 --- a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.html +++ b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.html @@ -172,7 +172,7 @@ - (A) {{__("ITC Available (whether in full op part)")}} + (A) {{__("ITC Available (whether in full or part)")}} diff --git a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py index a5dd5a2e094..3ddcc58867e 100644 --- a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py +++ b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py @@ -3,148 +3,21 @@ # For license information, please see license.txt from __future__ import unicode_literals +import os +import json import frappe +from six import iteritems from frappe import _ from frappe.model.document import Document -import json -from six import iteritems -from frappe.utils import flt, getdate +from frappe.utils import flt, cstr from erpnext.regional.india import state_numbers class GSTR3BReport(Document): - def before_save(self): - + def validate(self): self.get_data() def get_data(self): - - self.report_dict = { - "gstin": "", - "ret_period": "", - "inward_sup": { - "isup_details": [ - { - "ty": "GST", - "intra": 0, - "inter": 0 - }, - { - "ty": "NONGST", - "inter": 0, - "intra": 0 - } - ] - }, - "sup_details": { - "osup_zero": { - "csamt": 0, - "txval": 0, - "iamt": 0 - }, - "osup_nil_exmp": { - "txval": 0 - }, - "osup_det": { - "samt": 0, - "csamt": 0, - "txval": 0, - "camt": 0, - "iamt": 0 - }, - "isup_rev": { - "samt": 0, - "csamt": 0, - "txval": 0, - "camt": 0, - "iamt": 0 - }, - "osup_nongst": { - "txval": 0, - } - }, - "inter_sup": { - "unreg_details": [], - "comp_details": [], - "uin_details": [] - }, - "itc_elg": { - "itc_avl": [ - { - "csamt": 0, - "samt": 0, - "ty": "IMPG", - "camt": 0, - "iamt": 0 - }, - { - "csamt": 0, - "samt": 0, - "ty": "IMPS", - "camt": 0, - "iamt": 0 - }, - { - "samt": 0, - "csamt": 0, - "ty": "ISRC", - "camt": 0, - "iamt": 0 - }, - { - "ty": "ISD", - "iamt": 0, - "camt": 0, - "samt": 0, - "csamt": 0 - }, - { - "samt": 0, - "csamt": 0, - "ty": "OTH", - "camt": 0, - "iamt": 0 - } - ], - "itc_rev": [ - { - "ty": "RUL", - "iamt": 0, - "camt": 0, - "samt": 0, - "csamt": 0 - }, - { - "ty": "OTH", - "iamt": 0, - "camt": 0, - "samt": 0, - "csamt": 0 - } - ], - "itc_net": { - "samt": 0, - "csamt": 0, - "camt": 0, - "iamt": 0 - }, - "itc_inelg": [ - { - "ty": "RUL", - "iamt": 0, - "camt": 0, - "samt": 0, - "csamt": 0 - }, - { - "ty": "OTH", - "iamt": 0, - "camt": 0, - "samt": 0, - "csamt": 0 - } - ] - } - } + self.report_dict = json.loads(get_json('gstr_3b_report_template')) self.gst_details = self.get_company_gst_details() self.report_dict["gstin"] = self.gst_details.get("gstin") @@ -152,23 +25,19 @@ class GSTR3BReport(Document): self.month_no = get_period(self.month) self.account_heads = self.get_account_heads() - outward_supply_tax_amounts = self.get_tax_amounts("Sales Invoice") - inward_supply_tax_amounts = self.get_tax_amounts("Purchase Invoice", reverse_charge="Y") + self.get_outward_supply_details("Sales Invoice") + self.set_outward_taxable_supplies() + + self.get_outward_supply_details("Purchase Invoice", reverse_charge=True) + self.set_supplies_liable_to_reverse_charge() + itc_details = self.get_itc_details() - - self.prepare_data("Sales Invoice", outward_supply_tax_amounts, "sup_details", "osup_det", ["Registered Regular"]) - self.prepare_data("Sales Invoice", outward_supply_tax_amounts, "sup_details", "osup_zero", ["SEZ", "Deemed Export", "Overseas"]) - self.prepare_data("Purchase Invoice", inward_supply_tax_amounts, "sup_details", "isup_rev", ["Unregistered", "Overseas"], reverse_charge="Y") - self.report_dict["sup_details"]["osup_nil_exmp"]["txval"] = flt(self.get_nil_rated_supply_value(), 2) self.set_itc_details(itc_details) - - inter_state_supplies = self.get_inter_state_supplies(self.gst_details.get("gst_state_number")) + self.get_itc_reversal_entries() inward_nil_exempt = self.get_inward_nil_exempt(self.gst_details.get("gst_state")) - self.set_inter_state_supply(inter_state_supplies) self.set_inward_nil_exempt(inward_nil_exempt) self.missing_field_invoices = self.get_missing_field_invoices() - self.json_output = frappe.as_json(self.report_dict) def set_inward_nil_exempt(self, inward_nil_exempt): @@ -178,189 +47,95 @@ class GSTR3BReport(Document): self.report_dict["inward_sup"]["isup_details"][1]["intra"] = flt(inward_nil_exempt.get("non_gst").get("intra"), 2) def set_itc_details(self, itc_details): - - itc_type_map = { + itc_eligible_type_map = { 'IMPG': 'Import Of Capital Goods', 'IMPS': 'Import Of Service', + 'ISRC': 'ITC on Reverse Charge', 'ISD': 'Input Service Distributor', 'OTH': 'All Other ITC' } + itc_ineligible_map = { + 'RUL': 'Ineligible As Per Section 17(5)', + 'OTH': 'Ineligible Others' + } + net_itc = self.report_dict["itc_elg"]["itc_net"] for d in self.report_dict["itc_elg"]["itc_avl"]: - - itc_type = itc_type_map.get(d["ty"]) - - if d["ty"] == 'ISRC': - reverse_charge = ["Y"] - itc_type = 'All Other ITC' - gst_category = ['Unregistered', 'Overseas'] - else: - gst_category = ['Unregistered', 'Overseas', 'Registered Regular'] - reverse_charge = ["N", "Y"] - - for account_head in self.account_heads: - for category in gst_category: - for charge_type in reverse_charge: - for key in [['iamt', 'igst_account'], ['camt', 'cgst_account'], ['samt', 'sgst_account'], ['csamt', 'cess_account']]: - d[key[0]] += flt(itc_details.get((category, itc_type, charge_type, account_head.get(key[1])), {}).get("amount"), 2) - + itc_type = itc_eligible_type_map.get(d["ty"]) for key in ['iamt', 'camt', 'samt', 'csamt']: + d[key] = flt(itc_details.get(itc_type, {}).get(key)) net_itc[key] += flt(d[key], 2) - for account_head in self.account_heads: - itc_inelg = self.report_dict["itc_elg"]["itc_inelg"][1] - for key in [['iamt', 'igst_account'], ['camt', 'cgst_account'], ['samt', 'sgst_account'], ['csamt', 'cess_account']]: - itc_inelg[key[0]] = flt(itc_details.get(("Ineligible", "N", account_head.get(key[1])), {}).get("amount"), 2) + for d in self.report_dict["itc_elg"]["itc_inelg"]: + itc_type = itc_ineligible_map.get(d["ty"]) + for key in ['iamt', 'camt', 'samt', 'csamt']: + d[key] = flt(itc_details.get(itc_type, {}).get(key)) - def prepare_data(self, doctype, tax_details, supply_type, supply_category, gst_category_list, reverse_charge="N"): + def get_itc_reversal_entries(self): + reversal_entries = frappe.db.sql(""" + SELECT ja.account, j.reversal_type, sum(credit_in_account_currency) as amount + FROM `tabJournal Entry` j, `tabJournal Entry Account` ja + where j.docstatus = 1 + and j.is_opening = 'No' + and ja.parent = j.name + and j.voucher_type = 'Reversal Of ITC' + and month(j.posting_date) = %s and year(j.posting_date) = %s + and j.company = %s and j.company_gstin = %s + GROUP BY ja.account, j.reversal_type""", (self.month_no, self.year, self.company, + self.gst_details.get("gstin")), as_dict=1) - account_map = { - 'sgst_account': 'samt', - 'cess_account': 'csamt', - 'cgst_account': 'camt', - 'igst_account': 'iamt' - } + net_itc = self.report_dict["itc_elg"]["itc_net"] - txval = 0 - total_taxable_value = self.get_total_taxable_value(doctype, reverse_charge) + for entry in reversal_entries: + if entry.reversal_type == 'As per rules 42 & 43 of CGST Rules': + index = 0 + else: + index = 1 - for gst_category in gst_category_list: - txval += total_taxable_value.get(gst_category,0) - for account_head in self.account_heads: - for account_type, account_name in iteritems(account_head): - if account_map.get(account_type) in self.report_dict.get(supply_type).get(supply_category): - self.report_dict[supply_type][supply_category][account_map.get(account_type)] += \ - flt(tax_details.get((account_name, gst_category), {}).get("amount"), 2) - - self.report_dict[supply_type][supply_category]["txval"] += flt(txval, 2) - - def set_inter_state_supply(self, inter_state_supply): - osup_det = self.report_dict["sup_details"]["osup_det"] - - for key, value in iteritems(inter_state_supply): - if key[0] == "Unregistered": - self.report_dict["inter_sup"]["unreg_details"].append(value) - - if key[0] == "Registered Composition": - self.report_dict["inter_sup"]["comp_details"].append(value) - - if key[0] == "UIN Holders": - self.report_dict["inter_sup"]["uin_details"].append(value) - - def get_total_taxable_value(self, doctype, reverse_charge): - - return frappe._dict(frappe.db.sql(""" - select gst_category, sum(net_total) as total - from `tab{doctype}` - where docstatus = 1 and month(posting_date) = %s - and year(posting_date) = %s and reverse_charge = %s - and company = %s and company_gstin = %s - group by gst_category - """ #nosec - .format(doctype = doctype), (self.month_no, self.year, reverse_charge, self.company, self.gst_details.get("gstin")))) + for key in ['camt', 'samt', 'iamt', 'csamt']: + if entry.account in self.account_heads.get(key): + self.report_dict["itc_elg"]["itc_rev"][index][key] += flt(entry.amount) + net_itc[key] -= flt(entry.amount) def get_itc_details(self): - itc_amount = frappe.db.sql(""" - select s.gst_category, sum(t.base_tax_amount_after_discount_amount) as tax_amount, - t.account_head, s.eligibility_for_itc, s.reverse_charge - from `tabPurchase Invoice` s , `tabPurchase Taxes and Charges` t - where s.docstatus = 1 and t.parent = s.name - and month(s.posting_date) = %s and year(s.posting_date) = %s and s.company = %s - and s.company_gstin = %s - group by t.account_head, s.gst_category, s.eligibility_for_itc - """, - (self.month_no, self.year, self.company, self.gst_details.get("gstin")), as_dict=1) + itc_amounts = frappe.db.sql(""" + SELECT eligibility_for_itc, sum(itc_integrated_tax) as itc_integrated_tax, + sum(itc_central_tax) as itc_central_tax, + sum(itc_state_tax) as itc_state_tax, + sum(itc_cess_amount) as itc_cess_amount + FROM `tabPurchase Invoice` + WHERE docstatus = 1 + and is_opening = 'No' + and month(posting_date) = %s and year(posting_date) = %s and company = %s + and company_gstin = %s + GROUP BY eligibility_for_itc + """, (self.month_no, self.year, self.company, self.gst_details.get("gstin")), as_dict=1) itc_details = {} - - for d in itc_amount: - itc_details.setdefault((d.gst_category, d.eligibility_for_itc, d.reverse_charge, d.account_head),{ - "amount": d.tax_amount + for d in itc_amounts: + itc_details.setdefault(d.eligibility_for_itc, { + 'iamt': d.itc_integrated_tax, + 'camt': d.itc_central_tax, + 'samt': d.itc_state_tax, + 'csamt': d.itc_cess_amount }) return itc_details - def get_nil_rated_supply_value(self): - - return frappe.db.sql(""" - select sum(i.base_amount) as total from - `tabSales Invoice Item` i, `tabSales Invoice` s - where s.docstatus = 1 and i.parent = s.name and i.is_nil_exempt = 1 - and month(s.posting_date) = %s and year(s.posting_date) = %s - and s.company = %s and s.company_gstin = %s""", - (self.month_no, self.year, self.company, self.gst_details.get("gstin")), as_dict=1)[0].total - - def get_inter_state_supplies(self, state_number): - inter_state_supply_tax = frappe.db.sql(""" select t.account_head, t.tax_amount_after_discount_amount as tax_amount, - s.name, s.net_total, s.place_of_supply, s.gst_category from `tabSales Invoice` s, `tabSales Taxes and Charges` t - where t.parent = s.name and s.docstatus = 1 and month(s.posting_date) = %s and year(s.posting_date) = %s - and s.company = %s and s.company_gstin = %s and s.gst_category in ('Unregistered', 'Registered Composition', 'UIN Holders') - """, (self.month_no, self.year, self.company, self.gst_details.get("gstin")), as_dict=1) - - inter_state_supply_tax_mapping = {} - inter_state_supply_details = {} - - for d in inter_state_supply_tax: - inter_state_supply_tax_mapping.setdefault(d.name, { - 'place_of_supply': d.place_of_supply, - 'taxable_value': d.net_total, - 'gst_category': d.gst_category, - 'camt': 0.0, - 'samt': 0.0, - 'iamt': 0.0, - 'csamt': 0.0 - }) - - if d.account_head in [a.cgst_account for a in self.account_heads]: - inter_state_supply_tax_mapping[d.name]['camt'] += d.tax_amount - - if d.account_head in [a.sgst_account for a in self.account_heads]: - inter_state_supply_tax_mapping[d.name]['samt'] += d.tax_amount - - if d.account_head in [a.igst_account for a in self.account_heads]: - inter_state_supply_tax_mapping[d.name]['iamt'] += d.tax_amount - - if d.account_head in [a.cess_account for a in self.account_heads]: - inter_state_supply_tax_mapping[d.name]['csamt'] += d.tax_amount - - for key, value in iteritems(inter_state_supply_tax_mapping): - if value.get('place_of_supply'): - osup_det = self.report_dict["sup_details"]["osup_det"] - osup_det["txval"] = flt(osup_det["txval"] + value['taxable_value'], 2) - osup_det["iamt"] = flt(osup_det["iamt"] + value['iamt'], 2) - osup_det["camt"] = flt(osup_det["camt"] + value['camt'], 2) - osup_det["samt"] = flt(osup_det["samt"] + value['samt'], 2) - osup_det["csamt"] = flt(osup_det["csamt"] + value['csamt'], 2) - - if state_number != value.get('place_of_supply').split("-")[0]: - inter_state_supply_details.setdefault((value.get('gst_category'), value.get('place_of_supply')), { - "txval": 0.0, - "pos": value.get('place_of_supply').split("-")[0], - "iamt": 0.0 - }) - - inter_state_supply_details[(value.get('gst_category'), value.get('place_of_supply'))]['txval'] += value['taxable_value'] - inter_state_supply_details[(value.get('gst_category'), value.get('place_of_supply'))]['iamt'] += value['iamt'] - - return inter_state_supply_details - def get_inward_nil_exempt(self, state): - inward_nil_exempt = frappe.db.sql(""" select p.place_of_supply, sum(i.base_amount) as base_amount, - i.is_nil_exempt, i.is_non_gst from `tabPurchase Invoice` p , `tabPurchase Invoice Item` i - where p.docstatus = 1 and p.name = i.parent + inward_nil_exempt = frappe.db.sql(""" + SELECT p.place_of_supply, sum(i.base_amount) as base_amount, i.is_nil_exempt, i.is_non_gst + FROM `tabPurchase Invoice` p , `tabPurchase Invoice Item` i + WHERE p.docstatus = 1 and p.name = i.parent + and p.is_opening = 'No' and p.gst_category != 'Registered Composition' - and (i.is_nil_exempt = 1 or i.is_non_gst = 1) and - month(p.posting_date) = %s and year(p.posting_date) = %s and p.company = %s and p.company_gstin = %s - group by p.place_of_supply, i.is_nil_exempt, i.is_non_gst""", (self.month_no, self.year, self.company, self.gst_details.get("gstin")), as_dict=1) - - inward_nil_exempt += frappe.db.sql("""SELECT sum(base_net_total) as base_amount, gst_category, place_of_supply - FROM `tabPurchase Invoice` - WHERE docstatus = 1 and gst_category = 'Registered Composition' - and month(posting_date) = %s and year(posting_date) = %s - and company = %s and company_gstin = %s - group by place_of_supply""", (self.month_no, self.year, self.company, self.gst_details.get("gstin")), as_dict=1) + and (i.is_nil_exempt = 1 or i.is_non_gst = 1 or p.gst_category = 'Registered Composition') and + month(p.posting_date) = %s and year(p.posting_date) = %s + and p.company = %s and p.company_gstin = %s + GROUP BY p.place_of_supply, i.is_nil_exempt, i.is_non_gst""", + (self.month_no, self.year, self.company, self.gst_details.get("gstin")), as_dict=1) inward_nil_exempt_details = { "gst": { @@ -388,37 +163,193 @@ class GSTR3BReport(Document): return inward_nil_exempt_details - def get_tax_amounts(self, doctype, reverse_charge="N"): + def get_outward_supply_details(self, doctype, reverse_charge=None): + self.get_outward_tax_invoices(doctype, reverse_charge=reverse_charge) + self.get_outward_items(doctype) + self.get_outward_tax_details(doctype) + def get_outward_tax_invoices(self, doctype, reverse_charge=None): + self.invoices = [] + self.invoice_detail_map = {} + condition = '' + + if reverse_charge: + condition += "AND reverse_charge = 'Y'" + + invoice_details = frappe.db.sql(""" + SELECT + name, gst_category, export_type, place_of_supply + FROM + `tab{doctype}` + WHERE + docstatus = 1 + AND month(posting_date) = %s + AND year(posting_date) = %s + AND company = %s + AND company_gstin = %s + AND is_opening = 'No' + {reverse_charge} + ORDER BY name + """.format(doctype=doctype, reverse_charge=condition), (self.month_no, self.year, + self.company, self.gst_details.get("gstin")), as_dict=1) + + for d in invoice_details: + self.invoice_detail_map.setdefault(d.name, d) + self.invoices.append(d.name) + + def get_outward_items(self, doctype): + self.invoice_items = frappe._dict() + self.is_nil_exempt = [] + self.is_non_gst = [] + + if self.get('invoices'): + item_details = frappe.db.sql(""" + SELECT + item_code, parent, taxable_value, base_net_amount, item_tax_rate, + is_nil_exempt, is_non_gst + FROM + `tab%s Item` + WHERE parent in (%s) + """ % (doctype, ', '.join(['%s']*len(self.invoices))), tuple(self.invoices), as_dict=1) + + for d in item_details: + if d.item_code not in self.invoice_items.get(d.parent, {}): + self.invoice_items.setdefault(d.parent, {}).setdefault(d.item_code, + sum((i.get('taxable_value', 0) or i.get('base_net_amount', 0)) for i in item_details + if i.item_code == d.item_code and i.parent == d.parent)) + + if d.is_nil_exempt and d.item_code not in self.is_nil_exempt: + self.is_nil_exempt.append(d.item_code) + + if d.is_non_gst and d.item_code not in self.is_non_gst: + self.is_non_gst.append(d.item_code) + + def get_outward_tax_details(self, doctype): if doctype == "Sales Invoice": tax_template = 'Sales Taxes and Charges' elif doctype == "Purchase Invoice": tax_template = 'Purchase Taxes and Charges' - tax_amounts = frappe.db.sql(""" - select s.gst_category, sum(t.base_tax_amount_after_discount_amount) as tax_amount, t.account_head - from `tab{doctype}` s , `tab{template}` t - where s.docstatus = 1 and t.parent = s.name and s.reverse_charge = %s - and month(s.posting_date) = %s and year(s.posting_date) = %s and s.company = %s - and s.company_gstin = %s - group by t.account_head, s.gst_category - """ #nosec - .format(doctype=doctype, template=tax_template), - (reverse_charge, self.month_no, self.year, self.company, self.gst_details.get("gstin")), as_dict=1) + self.items_based_on_tax_rate = {} + self.invoice_cess = frappe._dict() + self.cgst_sgst_invoices = [] - tax_details = {} + if self.get('invoices'): + tax_details = frappe.db.sql(""" + SELECT + parent, account_head, item_wise_tax_detail, base_tax_amount_after_discount_amount + FROM `tab%s` + WHERE + parenttype = %s and docstatus = 1 + and parent in (%s) + ORDER BY account_head + """ % (tax_template, '%s', ', '.join(['%s']*len(self.invoices))), + tuple([doctype] + list(self.invoices))) - for d in tax_amounts: - tax_details.setdefault( - (d.account_head,d.gst_category),{ - "amount": d.get("tax_amount"), - } - ) + for parent, account, item_wise_tax_detail, tax_amount in tax_details: + if account in self.account_heads.get('csamt'): + self.invoice_cess.setdefault(parent, tax_amount) + else: + if item_wise_tax_detail: + try: + item_wise_tax_detail = json.loads(item_wise_tax_detail) + cgst_or_sgst = False + if account in self.account_heads.get('camt') \ + or account in self.account_heads.get('samt'): + cgst_or_sgst = True - return tax_details + for item_code, tax_amounts in item_wise_tax_detail.items(): + if not (cgst_or_sgst or account in self.account_heads.get('iamt') or + (item_code in self.is_non_gst + self.is_nil_exempt)): + continue + + tax_rate = tax_amounts[0] + if tax_rate: + if cgst_or_sgst: + tax_rate *= 2 + if parent not in self.cgst_sgst_invoices: + self.cgst_sgst_invoices.append(parent) + + rate_based_dict = self.items_based_on_tax_rate\ + .setdefault(parent, {}).setdefault(tax_rate, []) + if item_code not in rate_based_dict: + rate_based_dict.append(item_code) + except ValueError: + continue + + + if self.get('invoice_items'): + # Build itemised tax for export invoices, nil and exempted where tax table is blank + for invoice, items in iteritems(self.invoice_items): + if invoice not in self.items_based_on_tax_rate and (self.invoice_detail_map.get(invoice, {}).get('export_type') + == "Without Payment of Tax"): + self.items_based_on_tax_rate.setdefault(invoice, {}).setdefault(0, items.keys()) + + def set_outward_taxable_supplies(self): + inter_state_supply_details = {} + + for inv, items_based_on_rate in self.items_based_on_tax_rate.items(): + for rate, items in items_based_on_rate.items(): + for item_code, taxable_value in self.invoice_items.get(inv).items(): + if item_code in items: + if item_code in self.is_nil_exempt: + self.report_dict['sup_details']['osup_nil_exmp']['txval'] += taxable_value + elif item_code in self.is_non_gst: + self.report_dict['sup_details']['osup_nongst']['txval'] += taxable_value + elif rate == 0: + self.report_dict['sup_details']['osup_zero']['txval'] += taxable_value + #self.report_dict['sup_details']['osup_zero'][key] += tax_amount + else: + if inv in self.cgst_sgst_invoices: + tax_rate = rate/2 + self.report_dict['sup_details']['osup_det']['camt'] += (taxable_value * tax_rate /100) + self.report_dict['sup_details']['osup_det']['samt'] += (taxable_value * tax_rate /100) + self.report_dict['sup_details']['osup_det']['txval'] += taxable_value + else: + self.report_dict['sup_details']['osup_det']['iamt'] += (taxable_value * rate /100) + self.report_dict['sup_details']['osup_det']['txval'] += taxable_value + + gst_category = self.invoice_detail_map.get(inv, {}).get('gst_category') + place_of_supply = self.invoice_detail_map.get(inv, {}).get('place_of_supply', '00-Other Territory') + + if gst_category in ['Unregistered', 'Registered Composition', 'UIN Holders'] and \ + self.gst_details.get("gst_state") != place_of_supply.split("-")[1]: + inter_state_supply_details.setdefault((gst_category, place_of_supply), { + "txval": 0.0, + "pos": place_of_supply.split("-")[0], + "iamt": 0.0 + }) + inter_state_supply_details[(gst_category, place_of_supply)]['txval'] += taxable_value + inter_state_supply_details[(gst_category, place_of_supply)]['iamt'] += (taxable_value * rate /100) + + self.set_inter_state_supply(inter_state_supply_details) + + def set_supplies_liable_to_reverse_charge(self): + for inv, items_based_on_rate in self.items_based_on_tax_rate.items(): + for rate, items in items_based_on_rate.items(): + for item_code, taxable_value in self.invoice_items.get(inv).items(): + if item_code in items: + if inv in self.cgst_sgst_invoices: + tax_rate = rate/2 + self.report_dict['sup_details']['isup_rev']['camt'] += (taxable_value * tax_rate /100) + self.report_dict['sup_details']['isup_rev']['samt'] += (taxable_value * tax_rate /100) + self.report_dict['sup_details']['isup_rev']['txval'] += taxable_value + else: + self.report_dict['sup_details']['isup_rev']['iamt'] += (taxable_value * rate /100) + self.report_dict['sup_details']['isup_rev']['txval'] += taxable_value + + def set_inter_state_supply(self, inter_state_supply): + for key, value in iteritems(inter_state_supply): + if key[0] == "Unregistered": + self.report_dict["inter_sup"]["unreg_details"].append(value) + + if key[0] == "Registered Composition": + self.report_dict["inter_sup"]["comp_details"].append(value) + + if key[0] == "UIN Holders": + self.report_dict["inter_sup"]["uin_details"].append(value) def get_company_gst_details(self): - gst_details = frappe.get_all("Address", fields=["gstin", "gst_state", "gst_state_number"], filters={ @@ -431,20 +362,28 @@ class GSTR3BReport(Document): frappe.throw(_("Please enter GSTIN and state for the Company Address {0}").format(self.company_address)) def get_account_heads(self): + account_map = { + 'sgst_account': 'samt', + 'cess_account': 'csamt', + 'cgst_account': 'camt', + 'igst_account': 'iamt' + } - account_heads = frappe.get_all("GST Account", - fields=["cgst_account", "sgst_account", "igst_account", "cess_account"], - filters={ - "company":self.company - }) + account_heads = {} + gst_settings_accounts = frappe.get_all("GST Account", + filters={'company': self.company, 'is_reverse_charge_account': 0}, + fields=["cgst_account", "sgst_account", "igst_account", "cess_account"]) - if account_heads: - return account_heads - else: - frappe.throw(_("Please set account heads in GST Settings for Compnay {0}").format(self.company)) + if not gst_settings_accounts: + frappe.throw(_("Please set GST Accounts in GST Settings")) + + for d in gst_settings_accounts: + for acc, val in d.items(): + account_heads.setdefault(account_map.get(acc), []).append(val) + + return account_heads def get_missing_field_invoices(self): - missing_field_invoices = [] for doctype in ["Sales Invoice", "Purchase Invoice"]: @@ -456,26 +395,32 @@ class GSTR3BReport(Document): party_type = 'Supplier' party = 'supplier' - docnames = frappe.db.sql(""" - select t1.name from `tab{doctype}` t1, `tab{party_type}` t2 - where t1.docstatus = 1 and month(t1.posting_date) = %s and year(t1.posting_date) = %s + docnames = frappe.db.sql( + """ + SELECT t1.name FROM `tab{doctype}` t1, `tab{party_type}` t2 + WHERE t1.docstatus = 1 and t1.is_opening = 'No' + and month(t1.posting_date) = %s and year(t1.posting_date) = %s and t1.company = %s and t1.place_of_supply IS NULL and t1.{party} = t2.name and t2.gst_category != 'Overseas' - """.format(doctype = doctype, party_type = party_type, party=party), (self.month_no, self.year, self.company), as_dict=1) #nosec + """.format(doctype = doctype, party_type = party_type, + party=party) ,(self.month_no, self.year, self.company), as_dict=1) #nosec for d in docnames: missing_field_invoices.append(d.name) return ",".join(missing_field_invoices) -def get_state_code(state): +def get_json(template): + file_path = os.path.join(os.path.dirname(__file__), '{template}.json'.format(template=template)) + with open(file_path, 'r') as f: + return cstr(f.read()) +def get_state_code(state): state_code = state_numbers.get(state) return state_code def get_period(month, year=None): - month_no = { "January": 1, "February": 2, @@ -499,13 +444,11 @@ def get_period(month, year=None): @frappe.whitelist() def view_report(name): - json_data = frappe.get_value("GSTR 3B Report", name, 'json_output') return json.loads(json_data) @frappe.whitelist() def make_json(name): - json_data = frappe.get_value("GSTR 3B Report", name, 'json_output') file_name = "GST3B.json" frappe.local.response.filename = file_name diff --git a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report_template.json b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report_template.json new file mode 100644 index 00000000000..a68bd6a6e59 --- /dev/null +++ b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report_template.json @@ -0,0 +1,127 @@ +{ + "gstin": "", + "ret_period": "", + "inward_sup": { + "isup_details": [ + { + "ty": "GST", + "intra": 0, + "inter": 0 + }, + { + "ty": "NONGST", + "inter": 0, + "intra": 0 + } + ] + }, + "sup_details": { + "osup_zero": { + "csamt": 0, + "txval": 0, + "iamt": 0 + }, + "osup_nil_exmp": { + "txval": 0 + }, + "osup_det": { + "samt": 0, + "csamt": 0, + "txval": 0, + "camt": 0, + "iamt": 0 + }, + "isup_rev": { + "samt": 0, + "csamt": 0, + "txval": 0, + "camt": 0, + "iamt": 0 + }, + "osup_nongst": { + "txval": 0 + } + }, + "inter_sup": { + "unreg_details": [], + "comp_details": [], + "uin_details": [] + }, + "itc_elg": { + "itc_avl": [ + { + "csamt": 0, + "samt": 0, + "ty": "IMPG", + "camt": 0, + "iamt": 0 + }, + { + "csamt": 0, + "samt": 0, + "ty": "IMPS", + "camt": 0, + "iamt": 0 + }, + { + "samt": 0, + "csamt": 0, + "ty": "ISRC", + "camt": 0, + "iamt": 0 + }, + { + "ty": "ISD", + "iamt": 0, + "camt": 0, + "samt": 0, + "csamt": 0 + }, + { + "samt": 0, + "csamt": 0, + "ty": "OTH", + "camt": 0, + "iamt": 0 + } + ], + "itc_rev": [ + { + "ty": "RUL", + "iamt": 0, + "camt": 0, + "samt": 0, + "csamt": 0 + }, + { + "ty": "OTH", + "iamt": 0, + "camt": 0, + "samt": 0, + "csamt": 0 + } + ], + "itc_net": { + "samt": 0, + "csamt": 0, + "camt": 0, + "iamt": 0 + }, + "itc_inelg": [ + { + "ty": "RUL", + "iamt": 0, + "camt": 0, + "samt": 0, + "csamt": 0 + }, + { + "ty": "OTH", + "iamt": 0, + "camt": 0, + "samt": 0, + "csamt": 0 + } + ] + } +} \ 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 ef8af24c42a..3857ce1cdb8 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 @@ -60,8 +60,7 @@ class TestGSTR3BReport(unittest.TestCase): output = json.loads(report.json_output) - self.assertEqual(output["sup_details"]["osup_det"]["iamt"], 36), - self.assertEqual(output["sup_details"]["osup_zero"]["iamt"], 18), + self.assertEqual(output["sup_details"]["osup_det"]["iamt"], 54) self.assertEqual(output["inter_sup"]["unreg_details"][0]["iamt"], 18), self.assertEqual(output["sup_details"]["osup_nil_exmp"]["txval"], 100), self.assertEqual(output["inward_sup"]["isup_details"][0]["intra"], 250) diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py index b12e152b14e..229e0c031e3 100644 --- a/erpnext/regional/india/setup.py +++ b/erpnext/regional/india/setup.py @@ -114,9 +114,12 @@ def add_print_formats(): def make_property_setters(patch=False): # GST rules do not allow for an invoice no. bigger than 16 characters + journal_entry_types = frappe.get_meta("Journal Entry").get_options("voucher_type").split("\n") + ['Reversal Of ITC'] + if not patch: make_property_setter('Sales Invoice', 'naming_series', 'options', 'SINV-.YY.-\nSRET-.YY.-', '') make_property_setter('Purchase Invoice', 'naming_series', 'options', 'PINV-.YY.-\nPRET-.YY.-', '') + make_property_setter('Journal Entry', 'voucher_type', 'options', '\n'.join(journal_entry_types), '') def make_custom_fields(update=True): hsn_sac_field = dict(fieldname='gst_hsn_code', label='HSN/SAC', @@ -198,15 +201,20 @@ def make_custom_fields(update=True): purchase_invoice_itc_fields = [ dict(fieldname='eligibility_for_itc', label='Eligibility For ITC', fieldtype='Select', insert_after='reason_for_issuing_document', print_hide=1, - options='Input Service Distributor\nImport Of Service\nImport Of Capital Goods\nIneligible\nAll Other ITC', default="All Other ITC"), + options='Input Service Distributor\nImport Of Service\nImport Of Capital Goods\nITC on Reverse Charge\nIneligible As Per Section 17(5)\nIneligible Others\nAll Other ITC', + default="All Other ITC"), dict(fieldname='itc_integrated_tax', label='Availed ITC Integrated Tax', - fieldtype='Data', insert_after='eligibility_for_itc', print_hide=1), + fieldtype='Currency', insert_after='eligibility_for_itc', + options='Company:company:default_currency', print_hide=1), dict(fieldname='itc_central_tax', label='Availed ITC Central Tax', - fieldtype='Data', insert_after='itc_integrated_tax', print_hide=1), + fieldtype='Currency', insert_after='itc_integrated_tax', + options='Company:company:default_currency', print_hide=1), dict(fieldname='itc_state_tax', label='Availed ITC State/UT Tax', - fieldtype='Data', insert_after='itc_central_tax', print_hide=1), + fieldtype='Currency', insert_after='itc_central_tax', + options='Company:company:default_currency', print_hide=1), dict(fieldname='itc_cess_amount', label='Availed ITC Cess', - fieldtype='Data', insert_after='itc_state_tax', print_hide=1), + fieldtype='Currency', insert_after='itc_state_tax', + options='Company:company:default_currency', print_hide=1), ] sales_invoice_gst_fields = [ @@ -236,6 +244,23 @@ def make_custom_fields(update=True): depends_on="eval:doc.gst_category=='Overseas' "), ] + journal_entry_fields = [ + dict(fieldname='reversal_type', label='Reversal Type', + fieldtype='Select', insert_after='voucher_type', print_hide=1, + options="As per rules 42 & 43 of CGST Rules\nOthers", + depends_on="eval:doc.voucher_type=='Reversal Of ITC'", + mandatory_depends_on="eval:doc.voucher_type=='Reversal Of ITC'"), + dict(fieldname='company_address', label='Company Address', + fieldtype='Link', options='Address', insert_after='reversal_type', + print_hide=1, depends_on="eval:doc.voucher_type=='Reversal Of ITC'", + mandatory_depends_on="eval:doc.voucher_type=='Reversal Of ITC'"), + dict(fieldname='company_gstin', label='Company GSTIN', + fieldtype='Data', read_only=1, insert_after='company_address', print_hide=1, + fetch_from='company_address.gstin', + depends_on="eval:doc.voucher_type=='Reversal Of ITC'", + mandatory_depends_on="eval:doc.voucher_type=='Reversal Of ITC'") + ] + inter_state_gst_field = [ dict(fieldname='is_inter_state', label='Is Inter State', fieldtype='Check', insert_after='disabled', print_hide=1), @@ -430,13 +455,13 @@ def make_custom_fields(update=True): dict(fieldname='einvoice_section', label='E-Invoice Fields', fieldtype='Section Break', insert_after='gst_vehicle_type', print_hide=1, hidden=1), - + dict(fieldname='ack_no', label='Ack. No.', fieldtype='Data', read_only=1, hidden=1, insert_after='einvoice_section', no_copy=1, print_hide=1), - + dict(fieldname='ack_date', label='Ack. Date', fieldtype='Data', read_only=1, hidden=1, insert_after='ack_no', no_copy=1, print_hide=1), - dict(fieldname='irn_cancel_date', label='Cancel Date', fieldtype='Data', read_only=1, hidden=1, insert_after='ack_date', + dict(fieldname='irn_cancel_date', label='Cancel Date', fieldtype='Data', read_only=1, hidden=1, insert_after='ack_date', no_copy=1, print_hide=1), dict(fieldname='signed_einvoice', label='Signed E-Invoice', fieldtype='Code', options='JSON', hidden=1, insert_after='irn_cancel_date', @@ -469,6 +494,7 @@ def make_custom_fields(update=True): 'Purchase Receipt': purchase_invoice_gst_fields, 'Sales Invoice': sales_invoice_gst_category + invoice_gst_fields + sales_invoice_shipping_fields + sales_invoice_gst_fields + si_ewaybill_fields + si_einvoice_fields, 'Delivery Note': sales_invoice_gst_fields + ewaybill_fields + sales_invoice_shipping_fields + delivery_note_gst_category, + 'Journal Entry': journal_entry_fields, 'Sales Order': sales_invoice_gst_fields, 'Tax Category': inter_state_gst_field, 'Item': [ @@ -486,7 +512,7 @@ def make_custom_fields(update=True): 'Sales Invoice Item': [hsn_sac_field, nil_rated_exempt, is_non_gst, taxable_value], '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], + 'Purchase Invoice Item': [hsn_sac_field, nil_rated_exempt, is_non_gst, taxable_value], 'Material Request Item': [hsn_sac_field, nil_rated_exempt, is_non_gst], 'Salary Component': [ dict(fieldname= 'component_type', diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py index 052d7bdedf8..ca679e43d2e 100644 --- a/erpnext/regional/india/utils.py +++ b/erpnext/regional/india/utils.py @@ -204,8 +204,6 @@ def get_regional_address_details(party_details, doctype, company): if doctype in ("Sales Invoice", "Delivery Note", "Sales Order"): master_doctype = "Sales Taxes and Charges Template" - - get_tax_template_for_sez(party_details, master_doctype, company, 'Customer') get_tax_template_based_on_category(master_doctype, company, party_details) if party_details.get('taxes_and_charges'): @@ -216,7 +214,6 @@ def get_regional_address_details(party_details, doctype, company): elif doctype in ("Purchase Invoice", "Purchase Order", "Purchase Receipt"): master_doctype = "Purchase Taxes and Charges Template" - get_tax_template_for_sez(party_details, master_doctype, company, 'Supplier') get_tax_template_based_on_category(master_doctype, company, party_details) if party_details.get('taxes_and_charges'): @@ -283,20 +280,6 @@ def get_tax_template(master_doctype, company, is_inter_state, state_code): {'company': company, 'disabled': 0, 'tax_category': tax_category.name}, 'name') return default_tax -def get_tax_template_for_sez(party_details, master_doctype, company, party_type): - - gst_details = frappe.db.get_value(party_type, {'name': party_details.get(frappe.scrub(party_type))}, - ['gst_category', 'export_type'], as_dict=1) - - if gst_details: - if gst_details.gst_category == 'SEZ' and gst_details.export_type == 'With Payment of Tax': - default_tax = frappe.db.get_value(master_doctype, {"company": company, "is_inter_state":1, "disabled":0, - "gst_state": number_state_mapping[party_details.company_gstin[:2]]}) - - party_details["taxes_and_charges"] = default_tax - party_details.taxes = get_taxes_and_charges(master_doctype, default_tax) - - def calculate_annual_eligible_hra_exemption(doc): basic_component, hra_component = frappe.db.get_value('Company', doc.company, ["basic_component", "hra_component"]) if not (basic_component and hra_component): @@ -697,10 +680,19 @@ def validate_state_code(state_code, address): return int(state_code) @frappe.whitelist() -def get_gst_accounts(company, account_wise=False): +def get_gst_accounts(company=None, account_wise=False, only_reverse_charge=0, only_non_reverse_charge=0): + filters={"parent": "GST Settings"} + + if company: + filters.update({'company': company}) + if only_reverse_charge: + filters.update({'is_reverse_charge_account': 1}) + elif only_non_reverse_charge: + filters.update({'is_reverse_charge_account': 0}) + gst_accounts = frappe._dict() gst_settings_accounts = frappe.get_all("GST Account", - filters={"parent": "GST Settings", "company": company}, + filters=filters, fields=["cgst_account", "sgst_account", "igst_account", "cess_account"]) if not gst_settings_accounts and not frappe.flags.in_test: @@ -715,101 +707,63 @@ def get_gst_accounts(company, account_wise=False): return gst_accounts -def update_grand_total_for_rcm(doc, method): +def validate_reverse_charge_transaction(doc, method): country = frappe.get_cached_value('Company', doc.company, 'country') if country != 'India': return - gst_tax, base_gst_tax = get_gst_tax_amount(doc) - - if not base_gst_tax: - return + base_gst_tax = 0 + base_reverse_charge_booked = 0 if doc.reverse_charge == 'Y': - doc.taxes_and_charges_added -= gst_tax - doc.total_taxes_and_charges -= gst_tax - doc.base_taxes_and_charges_added -= base_gst_tax - doc.base_total_taxes_and_charges -= base_gst_tax + gst_accounts = get_gst_accounts(doc.company, only_reverse_charge=1) + reverse_charge_accounts = gst_accounts.get('cgst_account') + gst_accounts.get('sgst_account') \ + + gst_accounts.get('igst_account') - update_totals(gst_tax, base_gst_tax, doc) - -def update_totals(gst_tax, base_gst_tax, doc): - doc.base_grand_total -= base_gst_tax - doc.grand_total -= gst_tax - - if doc.meta.get_field("rounded_total"): - if doc.is_rounded_total_disabled(): - doc.outstanding_amount = doc.grand_total - else: - doc.rounded_total = round_based_on_smallest_currency_fraction(doc.grand_total, - doc.currency, doc.precision("rounded_total")) - - doc.rounding_adjustment += flt(doc.rounded_total - doc.grand_total, - doc.precision("rounding_adjustment")) - - doc.outstanding_amount = doc.rounded_total or doc.grand_total - - doc.in_words = money_in_words(doc.grand_total, doc.currency) - doc.base_in_words = money_in_words(doc.base_grand_total, erpnext.get_company_currency(doc.company)) - doc.set_payment_schedule() - -def make_regional_gl_entries(gl_entries, doc): - country = frappe.get_cached_value('Company', doc.company, 'country') - - if country != 'India': - return gl_entries - - gst_tax, base_gst_tax = get_gst_tax_amount(doc) - - if not base_gst_tax: - return gl_entries - - if doc.reverse_charge == 'Y': - gst_accounts = get_gst_accounts(doc.company) - gst_account_list = gst_accounts.get('cgst_account') + gst_accounts.get('sgst_account') \ + gst_accounts = get_gst_accounts(doc.company, only_non_reverse_charge=1) + non_reverse_charge_accounts = gst_accounts.get('cgst_account') + gst_accounts.get('sgst_account') \ + gst_accounts.get('igst_account') for tax in doc.get('taxes'): - if tax.category not in ("Total", "Valuation and Total"): - continue + if tax.account_head in non_reverse_charge_accounts: + if tax.add_deduct_tax == 'Add': + base_gst_tax += tax.base_tax_amount_after_discount_amount + else: + base_gst_tax += tax.base_tax_amount_after_discount_amount + elif tax.account_head in reverse_charge_accounts: + if tax.add_deduct_tax == 'Add': + base_reverse_charge_booked += tax.base_tax_amount_after_discount_amount + else: + base_reverse_charge_booked += tax.base_tax_amount_after_discount_amount - dr_or_cr = "credit" if tax.add_deduct_tax == "Add" else "debit" - if flt(tax.base_tax_amount_after_discount_amount) and tax.account_head in gst_account_list: - account_currency = get_account_currency(tax.account_head) + if base_gst_tax != base_reverse_charge_booked: + msg = _("Booked reverse charge is not equal to applied tax amount") + msg += "
" + msg += _("Please refer {gst_document_link} to learn more about how to setup and create reverse charge invoice").format( + gst_document_link='GST Documentation') - gl_entries.append(doc.get_gl_dict( - { - "account": tax.account_head, - "cost_center": tax.cost_center, - "posting_date": doc.posting_date, - "against": doc.supplier, - dr_or_cr: tax.base_tax_amount_after_discount_amount, - dr_or_cr + "_in_account_currency": tax.base_tax_amount_after_discount_amount \ - if account_currency==doc.company_currency \ - else tax.tax_amount_after_discount_amount - }, account_currency, item=tax) - ) + frappe.throw(msg) - return gl_entries +def update_itc_availed_fields(doc, method): + country = frappe.get_cached_value('Company', doc.company, 'country') -def get_gst_tax_amount(doc): - gst_accounts = get_gst_accounts(doc.company) - gst_account_list = gst_accounts.get('cgst_account', []) + gst_accounts.get('sgst_account', []) \ - + gst_accounts.get('igst_account', []) + if country != 'India': + return - base_gst_tax = 0 - gst_tax = 0 + # Initialize values + doc.itc_integrated_tax = doc.itc_state_tax = doc.itc_central_tax = doc.itc_cess_amount = 0 + gst_accounts = get_gst_accounts(doc.company, only_non_reverse_charge=1) for tax in doc.get('taxes'): - if tax.category not in ("Total", "Valuation and Total"): - continue - - if flt(tax.base_tax_amount_after_discount_amount) and tax.account_head in gst_account_list: - base_gst_tax += tax.base_tax_amount_after_discount_amount - gst_tax += tax.tax_amount_after_discount_amount - - return gst_tax, base_gst_tax + if tax.account_head in gst_accounts.get('igst_account', []): + doc.itc_integrated_tax += flt(tax.base_tax_amount_after_discount_amount) + if tax.account_head in gst_accounts.get('sgst_account', []): + doc.itc_state_tax += flt(tax.base_tax_amount_after_discount_amount) + if tax.account_head in gst_accounts.get('cgst_account', []): + doc.itc_central_tax += flt(tax.base_tax_amount_after_discount_amount) + if tax.account_head in gst_accounts.get('cess_account', []): + doc.itc_cess_amount += flt(tax.base_tax_amount_after_discount_amount) @frappe.whitelist() def get_regional_round_off_accounts(company, account_list): diff --git a/erpnext/regional/report/gstr_1/gstr_1.js b/erpnext/regional/report/gstr_1/gstr_1.js index 1a7ff2bf5a6..444f5dbb8ca 100644 --- a/erpnext/regional/report/gstr_1/gstr_1.js +++ b/erpnext/regional/report/gstr_1/gstr_1.js @@ -46,7 +46,13 @@ frappe.query_reports["GSTR-1"] = { "label": __("Type of Business"), "fieldtype": "Select", "reqd": 1, - "options": ["B2B", "B2C Large", "B2C Small", "CDNR", "EXPORT"], + "options": [ + { "value": "B2B", "label": __("B2B Invoices - 4A, 4B, 4C, 6B, 6C") }, + { "value": "B2C Large", "label": __("B2C(Large) Invoices - 5A, 5B") }, + { "value": "B2C Small", "label": __("B2C(Small) Invoices - 7") }, + { "value": "CDNR-REG", "label": __("Credit/Debit Notes (Registered) - 9B") }, + { "value": "EXPORT", "label": __("Export Invoice - 6A") } + ], "default": "B2B" } ], diff --git a/erpnext/regional/report/gstr_1/gstr_1.py b/erpnext/regional/report/gstr_1/gstr_1.py index 808fd3a2cc9..1e28a40f811 100644 --- a/erpnext/regional/report/gstr_1/gstr_1.py +++ b/erpnext/regional/report/gstr_1/gstr_1.py @@ -32,6 +32,7 @@ class Gstr1Report(object): reverse_charge, return_against, is_return, + is_debit_note, gst_category, export_type, port_code, @@ -42,7 +43,7 @@ class Gstr1Report(object): def run(self): self.get_columns() - self.gst_accounts = get_gst_accounts(self.filters.company) + self.gst_accounts = get_gst_accounts(self.filters.company, only_non_reverse_charge=1) self.get_invoice_data() if self.invoices: @@ -62,9 +63,9 @@ class Gstr1Report(object): for rate, items in items_based_on_rate.items(): row, taxable_value = self.get_row_data_for_invoice(inv, invoice_details, rate, items) - if self.filters.get("type_of_business") == "CDNR": + if self.filters.get("type_of_business") == "CDNR-REG": row.append("Y" if invoice_details.posting_date <= date(2017, 7, 1) else "N") - row.append("C" if invoice_details.return_against else "R") + row.append("C" if invoice_details.is_return else "D") if taxable_value: self.data.append(row) @@ -105,7 +106,7 @@ class Gstr1Report(object): def get_row_data_for_invoice(self, invoice, invoice_details, tax_rate, items): row = [] for fieldname in self.invoice_fields: - if self.filters.get("type_of_business") == "CDNR" and fieldname == "invoice_value": + if self.filters.get("type_of_business") == "CDNR-REG" and fieldname == "invoice_value": row.append(abs(invoice_details.base_rounded_total) or abs(invoice_details.base_grand_total)) elif fieldname == "invoice_value": row.append(invoice_details.base_rounded_total or invoice_details.base_grand_total) @@ -171,7 +172,7 @@ class Gstr1Report(object): if self.filters.get("type_of_business") == "B2B": - conditions += "and ifnull(gst_category, '') in ('Registered Regular', 'Deemed Export', 'SEZ') and is_return != 1" + conditions += "AND IFNULL(gst_category, '') in ('Registered Regular', 'Deemed Export', 'SEZ') AND is_return != 1" if self.filters.get("type_of_business") in ("B2C Large", "B2C Small"): b2c_limit = frappe.db.get_single_value('GST Settings', 'b2c_limit') @@ -179,19 +180,19 @@ class Gstr1Report(object): frappe.throw(_("Please set B2C Limit in GST Settings.")) if self.filters.get("type_of_business") == "B2C Large": - conditions += """ and ifnull(SUBSTR(place_of_supply, 1, 2),'') != ifnull(SUBSTR(company_gstin, 1, 2),'') - and grand_total > {0} and is_return != 1 and gst_category ='Unregistered' """.format(flt(b2c_limit)) + conditions += """ AND ifnull(SUBSTR(place_of_supply, 1, 2),'') != ifnull(SUBSTR(company_gstin, 1, 2),'') + AND grand_total > {0} AND is_return != 1 and gst_category ='Unregistered' """.format(flt(b2c_limit)) elif self.filters.get("type_of_business") == "B2C Small": - conditions += """ and ( + conditions += """ AND ( SUBSTR(place_of_supply, 1, 2) = SUBSTR(company_gstin, 1, 2) - or grand_total <= {0}) and is_return != 1 and gst_category ='Unregistered' """.format(flt(b2c_limit)) + OR grand_total <= {0}) and is_return != 1 AND gst_category ='Unregistered' """.format(flt(b2c_limit)) - elif self.filters.get("type_of_business") == "CDNR": - conditions += """ and is_return = 1 """ + elif self.filters.get("type_of_business") == "CDNR-REG": + conditions += """ AND (is_return = 1 OR is_debit_note = 1) AND IFNULL(gst_category, '') in ('Registered Regular', 'Deemed Export', 'SEZ')""" elif self.filters.get("type_of_business") == "EXPORT": - conditions += """ and is_return !=1 and gst_category = 'Overseas' """ + conditions += """ AND is_return !=1 and gst_category = 'Overseas' """ return conditions def get_invoice_items(self): @@ -403,7 +404,7 @@ class Gstr1Report(object): "width": 100 } ] - elif self.filters.get("type_of_business") == "CDNR": + elif self.filters.get("type_of_business") == "CDNR-REG": self.invoice_columns = [ { "fieldname": "customer_gstin", @@ -437,6 +438,17 @@ class Gstr1Report(object): "options": "Sales Invoice", "width":120 }, + { + "fieldname": "reverse_charge", + "label": "Reverse Charge", + "fieldtype": "Data" + }, + { + "fieldname": "export_type", + "label": "Export Type", + "fieldtype": "Data", + "hidden": 1 + }, { "fieldname": "reason_for_issuing_document", "label": "Reason For Issuing document", @@ -449,6 +461,11 @@ class Gstr1Report(object): "fieldtype": "Data", "width": 120 }, + { + "fieldname": "gst_category", + "label": "GST Category", + "fieldtype": "Data" + }, { "fieldname": "invoice_value", "label": "Invoice Value", @@ -458,10 +475,10 @@ class Gstr1Report(object): ] self.other_columns = [ { - "fieldname": "cess_amount", - "label": "Cess Amount", - "fieldtype": "Currency", - "width": 100 + "fieldname": "cess_amount", + "label": "Cess Amount", + "fieldtype": "Currency", + "width": 100 }, { "fieldname": "pre_gst", @@ -589,6 +606,12 @@ def get_json(filters, report_name, data): out = get_export_json(res) gst_json["exp"] = out + elif filters["type_of_business"] == 'CDNR-REG': + for item in report_data[:-1]: + res.setdefault(item["customer_gstin"], {}).setdefault(item["invoice_number"],[]).append(item) + + out = get_cdnr_reg_json(res, gstin) + gst_json["cdnr"] = out return { 'report_name': report_name, @@ -628,7 +651,6 @@ def get_b2b_json(res, gstin): return out def get_b2cs_json(data, gstin): - company_state_number = gstin[0:2] out = [] @@ -713,6 +735,54 @@ def get_export_json(res): return out +def get_cdnr_reg_json(res, gstin): + out = [] + + for gst_in in res: + cdnr_item, inv = {"ctin": gst_in, "nt": []}, [] + if not gst_in: continue + + for number, invoice in iteritems(res[gst_in]): + if not invoice[0]["place_of_supply"]: + frappe.throw(_("""{0} not entered in Invoice {1}. + Please update and try again""").format(frappe.bold("Place Of Supply"), + frappe.bold(invoice[0]['invoice_number']))) + + inv_item = { + "nt_num": invoice[0]["invoice_number"], + "nt_dt": getdate(invoice[0]["posting_date"]).strftime('%d-%m-%Y'), + "val": abs(flt(invoice[0]["invoice_value"])), + "ntty": invoice[0]["document_type"], + "pos": "%02d" % int(invoice[0]["place_of_supply"].split('-')[0]), + "rchrg": invoice[0]["reverse_charge"], + "inv_type": get_invoice_type_for_cdnr(invoice[0]) + } + + 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 + cdnr_item["nt"] = inv + out.append(cdnr_item) + + return out + +def get_invoice_type_for_cdnr(row): + if row.get('gst_category') == 'SEZ': + if row.get('export_type') == 'WPAY': + invoice_type = 'SEWP' + else: + invoice_type = 'SEWOP' + elif row.get('gst_category') == 'Deemed Export': + row.invoice_type = 'DE' + elif row.get('gst_category') == 'Registered Regular': + invoice_type = 'R' + + return invoice_type + def get_basic_invoice_detail(row): return { "inum": row["invoice_number"], From be3cde931303df533e673082954604ab2cca6ce8 Mon Sep 17 00:00:00 2001 From: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> Date: Fri, 14 May 2021 12:20:38 +0530 Subject: [PATCH 020/135] chore: Code clean up for purchase receipt GL (#25379) * chore: Code clean up for purchase receipt GL * fix: add params for debit and credit in account curreny * chore: Asset GL entry code cleanup * fix: Syntax error * fix: Update variable names * fix: function naming * fix: Add undefined variables * fix: Supplier warehouse fetching * fix: Linting issues --- .../purchase_receipt/purchase_receipt.py | 204 ++++++++---------- 1 file changed, 87 insertions(+), 117 deletions(-) diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index 61e60f39228..f1292d8cbdd 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -243,16 +243,23 @@ class PurchaseReceipt(BuyingController): def get_gl_entries(self, warehouse_account=None): from erpnext.accounts.general_ledger import process_gl_map + gl_entries = [] + self.make_item_gl_entries(gl_entries, warehouse_account=warehouse_account) + self.make_tax_gl_entries(gl_entries) + self.get_asset_gl_entry(gl_entries) + + return process_gl_map(gl_entries) + + def make_item_gl_entries(self, gl_entries, warehouse_account=None): stock_rbnb = self.get_company_default("stock_received_but_not_billed") landed_cost_entries = get_item_account_wise_additional_cost(self.name) expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation") auto_accounting_for_non_stock_items = cint(frappe.db.get_value('Company', self.company, 'enable_perpetual_inventory_for_non_stock_items')) - gl_entries = [] warehouse_with_no_account = [] - negative_expense_to_be_booked = 0.0 stock_items = self.get_stock_items() + for d in self.get("items"): if d.item_code in stock_items and flt(d.valuation_rate) and flt(d.qty): if warehouse_account.get(d.warehouse): @@ -263,21 +270,22 @@ class PurchaseReceipt(BuyingController): if not stock_value_diff: continue + warehouse_account_name = warehouse_account[d.warehouse]["account"] + warehouse_account_currency = warehouse_account[d.warehouse]["account_currency"] + supplier_warehouse_account = warehouse_account.get(self.supplier_warehouse, {}).get("account") + supplier_warehouse_account_currency = warehouse_account.get(self.supplier_warehouse, {}).get("account_currency") + remarks = self.get("remarks") or _("Accounting Entry for Stock") + # If PR is sub-contracted and fg item rate is zero - # in that case if account for shource and target warehouse are same, + # in that case if account for source and target warehouse are same, # then GL entries should not be posted if flt(stock_value_diff) == flt(d.rm_supp_cost) \ and warehouse_account.get(self.supplier_warehouse) \ - and warehouse_account[d.warehouse]["account"] == warehouse_account[self.supplier_warehouse]["account"]: + and warehouse_account_name == supplier_warehouse_account: continue - gl_entries.append(self.get_gl_dict({ - "account": warehouse_account[d.warehouse]["account"], - "against": stock_rbnb, - "cost_center": d.cost_center, - "remarks": self.get("remarks") or _("Accounting Entry for Stock"), - "debit": stock_value_diff - }, warehouse_account[d.warehouse]["account_currency"], item=d)) + self.add_gl_entry(gl_entries, warehouse_account_name, d.cost_center, stock_value_diff, 0.0, remarks, + stock_rbnb, account_currency=warehouse_account_currency, item=d) # GL Entry for from warehouse or Stock Received but not billed # Intentionally passed negative debit amount to avoid incorrect GL Entry validation @@ -287,43 +295,28 @@ class PurchaseReceipt(BuyingController): credit_amount = flt(d.base_net_amount, d.precision("base_net_amount")) \ if credit_currency == self.company_currency else flt(d.net_amount, d.precision("net_amount")) if credit_amount: - gl_entries.append(self.get_gl_dict({ - "account": warehouse_account[d.from_warehouse]['account'] \ - if d.from_warehouse else stock_rbnb, - "against": warehouse_account[d.warehouse]["account"], - "cost_center": d.cost_center, - "remarks": self.get("remarks") or _("Accounting Entry for Stock"), - "debit": -1 * flt(d.base_net_amount, d.precision("base_net_amount")), - "debit_in_account_currency": -1 * credit_amount - }, credit_currency, item=d)) + account = warehouse_account[d.from_warehouse]['account'] \ + if d.from_warehouse else stock_rbnb - negative_expense_to_be_booked += flt(d.item_tax_amount) + self.add_gl_entry(gl_entries, account, d.cost_center, + -1 * flt(d.base_net_amount, d.precision("base_net_amount")), 0.0, remarks, warehouse_account_name, + debit_in_account_currency=-1 * credit_amount, account_currency=credit_currency, item=d) - # Amount added through landed-cost-voucher + # Amount added through landed-cos-voucher if d.landed_cost_voucher_amount and landed_cost_entries: for account, amount in iteritems(landed_cost_entries[(d.item_code, d.name)]): account_currency = get_account_currency(account) - gl_entries.append(self.get_gl_dict({ - "account": account, - "account_currency": account_currency, - "against": warehouse_account[d.warehouse]["account"], - "cost_center": d.cost_center, - "remarks": self.get("remarks") or _("Accounting Entry for Stock"), - "credit": (flt(amount["base_amount"]) if (amount["base_amount"] or - account_currency!=self.company_currency) else flt(amount["amount"])), - "credit_in_account_currency": flt(amount["amount"]), - "project": d.project - }, item=d)) + credit_amount = (flt(amount["base_amount"]) if (amount["base_amount"] or + account_currency!=self.company_currency) else flt(amount["amount"])) + + self.add_gl_entry(gl_entries, account, d.cost_center, 0.0, credit_amount, remarks, + warehouse_account_name, credit_in_account_currency=flt(amount["amount"]), + account_currency=account_currency, project=d.project, item=d) # sub-contracting warehouse if flt(d.rm_supp_cost) and warehouse_account.get(self.supplier_warehouse): - gl_entries.append(self.get_gl_dict({ - "account": warehouse_account[self.supplier_warehouse]["account"], - "against": warehouse_account[d.warehouse]["account"], - "cost_center": d.cost_center, - "remarks": self.get("remarks") or _("Accounting Entry for Stock"), - "credit": flt(d.rm_supp_cost) - }, warehouse_account[self.supplier_warehouse]["account_currency"], item=d)) + self.add_gl_entry(gl_entries, supplier_warehouse_account, d.cost_center, 0.0, flt(d.rm_supp_cost), + remarks, warehouse_account_name, account_currency=supplier_warehouse_account_currency, item=d) # divisional loss adjustment valuation_amount_as_per_doc = flt(d.base_net_amount, d.precision("base_net_amount")) + \ @@ -340,46 +333,32 @@ class PurchaseReceipt(BuyingController): cost_center = d.cost_center or frappe.get_cached_value("Company", self.company, "cost_center") - gl_entries.append(self.get_gl_dict({ - "account": loss_account, - "against": warehouse_account[d.warehouse]["account"], - "cost_center": cost_center, - "remarks": self.get("remarks") or _("Accounting Entry for Stock"), - "debit": divisional_loss, - "project": d.project - }, credit_currency, item=d)) + self.add_gl_entry(gl_entries, loss_account, cost_center, divisional_loss, 0.0, remarks, + warehouse_account_name, account_currency=credit_currency, project=d.project, item=d) elif d.warehouse not in warehouse_with_no_account or \ d.rejected_warehouse not in warehouse_with_no_account: warehouse_with_no_account.append(d.warehouse) elif d.item_code not in stock_items and not d.is_fixed_asset and flt(d.qty) and auto_accounting_for_non_stock_items: - service_received_but_not_billed_account = self.get_company_default("service_received_but_not_billed") credit_currency = get_account_currency(service_received_but_not_billed_account) - - gl_entries.append(self.get_gl_dict({ - "account": service_received_but_not_billed_account, - "against": d.expense_account, - "cost_center": d.cost_center, - "remarks": self.get("remarks") or _("Accounting Entry for Service"), - "project": d.project, - "credit": d.amount, - "voucher_detail_no": d.name - }, credit_currency, item=d)) - debit_currency = get_account_currency(d.expense_account) + remarks = self.get("remarks") or _("Accounting Entry for Service") - gl_entries.append(self.get_gl_dict({ - "account": d.expense_account, - "against": service_received_but_not_billed_account, - "cost_center": d.cost_center, - "remarks": self.get("remarks") or _("Accounting Entry for Service"), - "project": d.project, - "debit": d.amount, - "voucher_detail_no": d.name - }, debit_currency, item=d)) + self.add_gl_entry(gl_entries, service_received_but_not_billed_account, d.cost_center, 0.0, d.amount, + remarks, d.expense_account, account_currency=credit_currency, project=d.project, + voucher_detail_no=d.name, item=d) - self.get_asset_gl_entry(gl_entries) + self.add_gl_entry(gl_entries, d.expense_account, d.cost_center, d.amount, 0.0, remarks, service_received_but_not_billed_account, + account_currency = debit_currency, project=d.project, voucher_detail_no=d.name, item=d) + + if warehouse_with_no_account: + frappe.msgprint(_("No accounting entries for the following warehouses") + ": \n" + + "\n".join(warehouse_with_no_account)) + + def make_tax_gl_entries(self, gl_entries): + expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation") + negative_expense_to_be_booked = sum([flt(d.item_tax_amount) for d in self.get('items')]) # Cost center-wise amount breakup for other charges included for valuation valuation_tax = {} for tax in self.get("taxes"): @@ -420,23 +399,33 @@ class PurchaseReceipt(BuyingController): applicable_amount = negative_expense_to_be_booked * (valuation_tax[tax.name] / total_valuation_amount) amount_including_divisional_loss -= applicable_amount - gl_entries.append( - self.get_gl_dict({ - "account": account, - "cost_center": tax.cost_center, - "credit": applicable_amount, - "remarks": self.remarks or _("Accounting Entry for Stock"), - "against": against_account - }, item=tax) - ) + self.add_gl_entry(gl_entries, account, tax.cost_center, 0.0, applicable_amount, self.remarks or _("Accounting Entry for Stock"), + against_account, item=tax) i += 1 - if warehouse_with_no_account: - frappe.msgprint(_("No accounting entries for the following warehouses") + ": \n" + - "\n".join(warehouse_with_no_account)) + def add_gl_entry(self, gl_entries, account, cost_center, debit, credit, remarks, against_account, + debit_in_account_currency=None, credit_in_account_currency=None, account_currency=None, + project=None, voucher_detail_no=None, item=None): + gl_entry = { + "account": account, + "cost_center": cost_center, + "debit": debit, + "credit": credit, + "against_account": against_account, + "remarks": remarks, + } - return process_gl_map(gl_entries) + if voucher_detail_no: + gl_entry.update({"voucher_detail_no": voucher_detail_no}) + + if debit_in_account_currency: + gl_entry.update({"debit_in_account_currency": debit_in_account_currency}) + + if credit_in_account_currency: + gl_entry.update({"credit_in_account_currency": credit_in_account_currency}) + + gl_entries.append(self.get_gl_dict(gl_entry, item=item)) def get_asset_gl_entry(self, gl_entries): for item in self.get("items"): @@ -458,30 +447,21 @@ class PurchaseReceipt(BuyingController): asset_amount = flt(item.net_amount) + flt(item.item_tax_amount/self.conversion_rate) base_asset_amount = flt(item.base_net_amount + item.item_tax_amount) + remarks = self.get("remarks") or _("Accounting Entry for Asset") cwip_account_currency = get_account_currency(cwip_account) # debit cwip account - gl_entries.append(self.get_gl_dict({ - "account": cwip_account, - "against": arbnb_account, - "cost_center": item.cost_center, - "remarks": self.get("remarks") or _("Accounting Entry for Asset"), - "debit": base_asset_amount, - "debit_in_account_currency": (base_asset_amount - if cwip_account_currency == self.company_currency else asset_amount) - }, item=item)) + debit_in_account_currency = (base_asset_amount + if cwip_account_currency == self.company_currency else asset_amount) + self.add_gl_entry(gl_entries, cwip_account, item.cost_center, base_asset_amount, 0.0, remarks, + arbnb_account, debit_in_account_currency=debit_in_account_currency, item=item) asset_rbnb_currency = get_account_currency(arbnb_account) # credit arbnb account - gl_entries.append(self.get_gl_dict({ - "account": arbnb_account, - "against": cwip_account, - "cost_center": item.cost_center, - "remarks": self.get("remarks") or _("Accounting Entry for Asset"), - "credit": base_asset_amount, - "credit_in_account_currency": (base_asset_amount - if asset_rbnb_currency == self.company_currency else asset_amount) - }, item=item)) + credit_in_account_currency = (base_asset_amount + if asset_rbnb_currency == self.company_currency else asset_amount) + self.add_gl_entry(gl_entries, arbnb_account, item.cost_center, 0.0, base_asset_amount, remarks, + cwip_account, credit_in_account_currency=credit_in_account_currency, item=item) def add_lcv_gl_entries(self, item, gl_entries): expenses_included_in_asset_valuation = self.get_company_default("expenses_included_in_asset_valuation") @@ -492,23 +472,13 @@ class PurchaseReceipt(BuyingController): # This returns company's default cwip account asset_account = get_asset_account("capital_work_in_progress_account", company=self.company) - gl_entries.append(self.get_gl_dict({ - "account": expenses_included_in_asset_valuation, - "against": asset_account, - "cost_center": item.cost_center, - "remarks": self.get("remarks") or _("Accounting Entry for Stock"), - "credit": flt(item.landed_cost_voucher_amount), - "project": item.project - }, item=item)) + remarks = self.get("remarks") or _("Accounting Entry for Stock") - gl_entries.append(self.get_gl_dict({ - "account": asset_account, - "against": expenses_included_in_asset_valuation, - "cost_center": item.cost_center, - "remarks": self.get("remarks") or _("Accounting Entry for Stock"), - "debit": flt(item.landed_cost_voucher_amount), - "project": item.project - }, item=item)) + self.add_gl_entry(gl_entries, expenses_included_in_asset_valuation, item.cost_center, 0.0, flt(item.landed_cost_voucher_amount), + remarks, asset_account, project=item.project, item=item) + + self.add_gl_entry(gl_entries, asset_account, item.cost_center, 0.0, flt(item.landed_cost_voucher_amount), + remarks, expenses_included_in_asset_valuation, project=item.project, item=item) def update_assets(self, item, valuation_rate): assets = frappe.db.get_all('Asset', From eca86290bc33773288af2110f214aca7993c497b Mon Sep 17 00:00:00 2001 From: Alan <2.alan.tom@gmail.com> Date: Fri, 14 May 2021 12:21:38 +0530 Subject: [PATCH 021/135] fix: show uom for item in selector dialog (#25697) --- erpnext/public/js/utils/serial_no_batch_selector.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/erpnext/public/js/utils/serial_no_batch_selector.js b/erpnext/public/js/utils/serial_no_batch_selector.js index 3333d569a77..a289ec415bf 100644 --- a/erpnext/public/js/utils/serial_no_batch_selector.js +++ b/erpnext/public/js/utils/serial_no_batch_selector.js @@ -77,6 +77,14 @@ erpnext.SerialNoBatchSelector = Class.extend({ label: __(me.has_batch && !me.has_serial_no ? 'Total Qty' : 'Qty'), default: flt(me.item.stock_qty), }, + { + fieldname: 'uom', + read_only: 1, + fieldtype: 'Link', + options: 'UOM', + label: __('UOM'), + default: me.item.uom + }, { fieldname: 'auto_fetch_button', fieldtype:'Button', From 98fc4195b34f5ff47c4062352244105e8074913b Mon Sep 17 00:00:00 2001 From: Alan <2.alan.tom@gmail.com> Date: Fri, 14 May 2021 12:22:28 +0530 Subject: [PATCH 022/135] fix: send emails on rfq submit (#25695) * fix: send emails on rfq submit * fix: check if email is present for supplier --- .../doctype/request_for_quotation/request_for_quotation.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py index b530d1ab241..180ba936661 100644 --- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py +++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py @@ -62,6 +62,7 @@ class RequestforQuotation(BuyingController): for supplier in self.suppliers: supplier.email_sent = 0 supplier.quote_status = 'Pending' + self.send_to_supplier() def on_cancel(self): frappe.db.set(self, 'status', 'Cancelled') @@ -81,7 +82,7 @@ class RequestforQuotation(BuyingController): def send_to_supplier(self): """Sends RFQ mail to involved suppliers.""" for rfq_supplier in self.suppliers: - if rfq_supplier.send_email: + if rfq_supplier.email_id is not None and rfq_supplier.send_email: self.validate_email_id(rfq_supplier) # make new user if required From 2aa401826e1ac2b8627bb11e94b13fbe568c6eb7 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Fri, 14 May 2021 12:34:50 +0530 Subject: [PATCH 023/135] fix: validation message of quality inspection in purchase receipt (#25666) --- erpnext/controllers/stock_controller.py | 3 +-- .../doctype/quality_inspection/test_quality_inspection.py | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py index b14c2745159..41ca404d9b8 100644 --- a/erpnext/controllers/stock_controller.py +++ b/erpnext/controllers/stock_controller.py @@ -379,8 +379,7 @@ class StockController(AccountsController): link = frappe.utils.get_link_to_form('Quality Inspection', d.quality_inspection) frappe.throw(_("Quality Inspection: {0} is not submitted for the item: {1} in row {2}").format(link, d.item_code, d.idx), QualityInspectionNotSubmittedError) - qa_failed = any([r.status=="Rejected" for r in qa_doc.readings]) - if qa_failed: + if qa_doc.status != 'Accepted': frappe.throw(_("Row {0}: Quality Inspection rejected for item {1}") .format(d.idx, d.item_code), QualityInspectionRejectedError) elif qa_required : diff --git a/erpnext/stock/doctype/quality_inspection/test_quality_inspection.py b/erpnext/stock/doctype/quality_inspection/test_quality_inspection.py index a7dfc9ee288..56b046a92e1 100644 --- a/erpnext/stock/doctype/quality_inspection/test_quality_inspection.py +++ b/erpnext/stock/doctype/quality_inspection/test_quality_inspection.py @@ -27,10 +27,11 @@ class TestQualityInspection(unittest.TestCase): dn.reload() self.assertRaises(QualityInspectionRejectedError, dn.submit) - frappe.db.set_value("Quality Inspection Reading", {"parent": qa.name}, "status", "Accepted") + frappe.db.set_value("Quality Inspection", qa.name, "status", "Accepted") dn.reload() dn.submit() + qa.reload() qa.cancel() dn.reload() dn.cancel() From 55c2fec6832152813f1abd9b2b8093cd0880e9fe Mon Sep 17 00:00:00 2001 From: Alan <2.alan.tom@gmail.com> Date: Fri, 14 May 2021 12:36:41 +0530 Subject: [PATCH 024/135] feat: add pending qty section to batch/serial selector dialog (#25519) * feat: add pending qty section to batch/serial selector dialog * fix: call attach in setup and refresh, fix conditional * refactor: camel to snake casing --- .../js/utils/serial_no_batch_selector.js | 76 ++++++++++++++++++- .../stock/doctype/stock_entry/stock_entry.js | 21 +++++ 2 files changed, 96 insertions(+), 1 deletion(-) diff --git a/erpnext/public/js/utils/serial_no_batch_selector.js b/erpnext/public/js/utils/serial_no_batch_selector.js index a289ec415bf..b5d3981ba7f 100644 --- a/erpnext/public/js/utils/serial_no_batch_selector.js +++ b/erpnext/public/js/utils/serial_no_batch_selector.js @@ -74,9 +74,10 @@ erpnext.SerialNoBatchSelector = Class.extend({ fieldname: 'qty', fieldtype:'Float', read_only: me.has_batch && !me.has_serial_no, - label: __(me.has_batch && !me.has_serial_no ? 'Total Qty' : 'Qty'), + label: __(me.has_batch && !me.has_serial_no ? 'Selected Qty' : 'Qty'), default: flt(me.item.stock_qty), }, + ...get_pending_qty_fields(me), { fieldname: 'uom', read_only: 1, @@ -181,6 +182,7 @@ erpnext.SerialNoBatchSelector = Class.extend({ if (this.has_batch && !this.has_serial_no) { this.update_total_qty(); + this.update_pending_qtys(); } this.dialog.show(); @@ -321,7 +323,21 @@ erpnext.SerialNoBatchSelector = Class.extend({ qty_field.set_input(total_qty); }, + update_pending_qtys: function() { + const pending_qty_field = this.dialog.fields_dict.pending_qty; + const total_selected_qty_field = this.dialog.fields_dict.total_selected_qty; + if (!pending_qty_field || !total_selected_qty_field) return; + + const me = this; + const required_qty = this.dialog.fields_dict.required_qty.value; + const selected_qty = this.dialog.fields_dict.qty.value; + const total_selected_qty = selected_qty + calc_total_selected_qty(me); + const pending_qty = required_qty - total_selected_qty; + + pending_qty_field.set_input(pending_qty); + total_selected_qty_field.set_input(total_selected_qty); + }, get_batch_fields: function() { var me = this; @@ -423,6 +439,7 @@ erpnext.SerialNoBatchSelector = Class.extend({ } me.update_total_qty(); + me.update_pending_qtys(); } }, ], @@ -519,3 +536,60 @@ erpnext.SerialNoBatchSelector = Class.extend({ ]; } }); + +function get_pending_qty_fields(me) { + if (!check_can_calculate_pending_qty(me)) return []; + const { frm: { doc: { fg_completed_qty }}, item: { item_code, stock_qty }} = me; + const { qty_consumed_per_unit } = erpnext.stock.bom.items[item_code]; + + const total_selected_qty = calc_total_selected_qty(me); + const required_qty = flt(fg_completed_qty) * flt(qty_consumed_per_unit); + const pending_qty = required_qty - (flt(stock_qty) + total_selected_qty); + + const pending_qty_fields = [ + { fieldtype: 'Section Break', label: __('Pending Quantity') }, + { + fieldname: 'required_qty', + read_only: 1, + fieldtype: 'Float', + label: __('Required Qty'), + default: required_qty + }, + { fieldtype: 'Column Break' }, + { + fieldname: 'total_selected_qty', + read_only: 1, + fieldtype: 'Float', + label: __('Total Selected Qty'), + default: total_selected_qty + }, + { fieldtype: 'Column Break' }, + { + fieldname: 'pending_qty', + read_only: 1, + fieldtype: 'Float', + label: __('Pending Qty'), + default: pending_qty + }, + ]; + return pending_qty_fields; +} + +function calc_total_selected_qty(me) { + const { frm: { doc: { items }}, item: { name, item_code }} = me; + const totalSelectedQty = items + .filter( item => ( item.name !== name ) && ( item.item_code === item_code ) ) + .map( item => flt(item.qty) ) + .reduce( (i, j) => i + j, 0); + return totalSelectedQty; +} + +function check_can_calculate_pending_qty(me) { + const { frm: { doc }, item } = me; + const docChecks = doc.bom_no + && doc.fg_completed_qty + && erpnext.stock.bom + && erpnext.stock.bom.name === doc.bom_no; + const itemChecks = !!item; + return docChecks && itemChecks; +} diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js index 772c8df96e1..daa1e511820 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.js +++ b/erpnext/stock/doctype/stock_entry/stock_entry.js @@ -107,6 +107,7 @@ frappe.ui.form.on('Stock Entry', { frappe.flags.hide_serial_batch_dialog = true; } }); + attach_bom_items(frm.doc.bom_no); }, setup_quality_inspection: function(frm) { @@ -311,6 +312,7 @@ frappe.ui.form.on('Stock Entry', { } frm.trigger("setup_quality_inspection"); + attach_bom_items(frm.doc.bom_no) }, stock_entry_type: function(frm){ @@ -919,6 +921,7 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({ method: "get_items", callback: function(r) { if(!r.exc) refresh_field("items"); + if(me.frm.doc.bom_no) attach_bom_items(me.frm.doc.bom_no) } }); } @@ -1064,4 +1067,22 @@ erpnext.stock.select_batch_and_serial_no = (frm, item) => { } +function attach_bom_items(bom_no) { + if (check_should_not_attach_bom_items(bom_no)) return + frappe.db.get_doc("BOM",bom_no).then(bom => { + const {name, items} = bom + erpnext.stock.bom = {name, items:{}} + items.forEach(item => { + erpnext.stock.bom.items[item.item_code] = item; + }); + }); +} + +function check_should_not_attach_bom_items(bom_no) { + return ( + bom_no === undefined || + (erpnext.stock.bom && erpnext.stock.bom.name === bom_no) + ); +} + $.extend(cur_frm.cscript, new erpnext.stock.StockEntry({frm: cur_frm})); From d8de7fccc2f27efe3b45b6ae1ba89ba8ab96521a Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Fri, 14 May 2021 19:17:28 +0530 Subject: [PATCH 025/135] feat: Show net values in Party Accounts --- .../report/general_ledger/general_ledger.js | 5 ++++ .../report/general_ledger/general_ledger.py | 27 +++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/erpnext/accounts/report/general_ledger/general_ledger.js b/erpnext/accounts/report/general_ledger/general_ledger.js index fb0d3599261..84f786814de 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.js +++ b/erpnext/accounts/report/general_ledger/general_ledger.js @@ -166,6 +166,11 @@ frappe.query_reports["General Ledger"] = { "fieldname": "show_cancelled_entries", "label": __("Show Cancelled Entries"), "fieldtype": "Check" + }, + { + "fieldname": "show_net_values_in_party_account", + "label": __("Show Net Values in Party Account"), + "fieldtype": "Check" } ] } diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py index b5d7992604f..562df4f6f7d 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.py +++ b/erpnext/accounts/report/general_ledger/general_ledger.py @@ -344,6 +344,9 @@ def get_accountwise_gle(filters, accounting_dimensions, gl_entries, gle_map): consolidated_gle = OrderedDict() group_by = group_by_field(filters.get('group_by')) + if filters.get('show_net_values_in_party_account'): + account_type_map = get_account_type_map(filters.get('company')) + def update_value_in_dict(data, key, gle): data[key].debit += flt(gle.debit) data[key].credit += flt(gle.credit) @@ -351,6 +354,24 @@ def get_accountwise_gle(filters, accounting_dimensions, gl_entries, gle_map): data[key].debit_in_account_currency += flt(gle.debit_in_account_currency) data[key].credit_in_account_currency += flt(gle.credit_in_account_currency) + if filters.get('show_net_values_in_party_account') and \ + account_type_map.get(data[key].account) in ('Receivable', 'Payable'): + net_value = flt(data[key].debit) - flt(data[key].credit) + net_value_in_account_currency = flt(data[key].debit_in_account_currency) \ + - flt(data[key].credit_in_account_currency) + + if net_value < 0: + dr_or_cr = 'credit' + rev_dr_or_cr = 'debit' + else: + dr_or_cr = 'debit' + rev_dr_or_cr = 'credit' + + data[key][dr_or_cr] = abs(net_value) + data[key][dr_or_cr+'_in_account_currency'] = abs(net_value_in_account_currency) + data[key][rev_dr_or_cr] = 0 + data[key][rev_dr_or_cr+'_in_account_currency'] = 0 + if data[key].against_voucher and gle.against_voucher: data[key].against_voucher += ', ' + gle.against_voucher @@ -388,6 +409,12 @@ def get_accountwise_gle(filters, accounting_dimensions, gl_entries, gle_map): return totals, entries +def get_account_type_map(company): + account_type_map = frappe._dict(frappe.get_all('Account', fields=['name', 'account_type'], + filters={'company': company}, as_list=1)) + + return account_type_map + def get_result_as_list(data, filters): balance, balance_in_account_currency = 0, 0 inv_details = get_supplier_invoice_details() From fd4743cc314c4c1f89ec2d6f7968f9fd478ae9b4 Mon Sep 17 00:00:00 2001 From: Anupam Date: Wed, 12 May 2021 16:17:32 +0530 Subject: [PATCH 026/135] refactor: timesheet --- .../doctype/sales_invoice/sales_invoice.js | 51 +- .../doctype/sales_invoice/sales_invoice.json | 3 +- .../doctype/sales_invoice/sales_invoice.py | 24 +- .../sales_invoice_timesheet.json | 233 +--- erpnext/hooks.py | 3 +- erpnext/patches.txt | 1 + .../v7_0/convert_timelog_to_timesheet.py | 2 +- .../doctype/timesheet/test_timesheet.py | 14 +- .../projects/doctype/timesheet/timesheet.js | 87 +- .../projects/doctype/timesheet/timesheet.json | 24 +- .../projects/doctype/timesheet/timesheet.py | 65 +- .../timesheet_detail/timesheet_detail.json | 1160 +++-------------- erpnext/projects/report/billing_summary.py | 4 +- ...ee_hours_utilization_based_on_timesheet.py | 6 +- .../test_employee_util.py | 4 +- .../test_project_profitability.py | 2 +- erpnext/public/js/utils.js | 12 + 17 files changed, 498 insertions(+), 1197 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js index 7c73ad6c90e..2b79e18358d 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js @@ -685,14 +685,16 @@ frappe.ui.form.on('Sales Invoice', { }, project: function(frm){ - frm.call({ - method: "add_timesheet_data", - doc: frm.doc, - callback: function(r, rt) { - refresh_field(['timesheets']) - } - }) - frm.refresh(); + if (!frm.doc.is_return) { + frm.call({ + method: "add_timesheet_data", + doc: frm.doc, + callback: function(r, rt) { + refresh_field(['timesheets']) + } + }) + frm.refresh(); + } }, onload: function(frm) { @@ -808,27 +810,45 @@ frappe.ui.form.on('Sales Invoice', { }, refresh: function(frm) { - if (frm.doc.project) { + if (frm.doc.project && frm.doc.docstatus===0 && !frm.doc.is_return) { frm.add_custom_button(__('Fetch Timesheet'), function() { let d = new frappe.ui.Dialog({ title: __('Fetch Timesheet'), fields: [ { - "label" : "From", + "label" : __("From"), "fieldname": "from_time", "fieldtype": "Date", "reqd": 1, }, + { + "label" : __("Currency"), + "fieldname": "currency", + "fieldtype": "Link", + "options": "Currency", + "default": frm.doc.currency, + "reqd": 1, + "read_only": 1 + }, { fieldtype: 'Column Break', fieldname: 'col_break_1', }, { - "label" : "To", + "label" : __("To"), "fieldname": "to_time", "fieldtype": "Date", "reqd": 1, - } + }, + { + "label" : __("Project"), + "fieldname": "project", + "fieldtype": "Link", + "options": "Project", + "default": frm.doc.project, + "reqd": 1, + "read_only": 1 + }, ], primary_action: function() { let data = d.get_values(); @@ -837,7 +857,8 @@ frappe.ui.form.on('Sales Invoice', { args: { from_time: data.from_time, to_time: data.to_time, - project: frm.doc.project + project: data.project, + currency: data.currency }, callback: function(r) { if(!r.exc) { @@ -845,9 +866,11 @@ frappe.ui.form.on('Sales Invoice', { frm.clear_table('timesheets') r.message.forEach((d) => { frm.add_child('timesheets',{ + 'activity_type': d.activity_type, + 'description': d.description, 'time_sheet': d.parent, 'billing_hours': d.billing_hours, - 'billing_amount': d.billing_amt, + 'billing_amount': d.billing_amount, 'timesheet_detail': d.name }); }); diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json index c6c67b4ddc1..607e4c43d0b 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json @@ -748,6 +748,7 @@ { "collapsible": 1, "collapsible_depends_on": "eval:doc.total_billing_amount > 0", + "depends_on": "eval: !doc.is_return", "fieldname": "time_sheet_list", "fieldtype": "Section Break", "hide_days": 1, @@ -1969,7 +1970,7 @@ "link_fieldname": "consolidated_invoice" } ], - "modified": "2021-04-15 23:57:58.766651", + "modified": "2021-05-13 17:53:26.185370", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice", diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index bb74a02606f..a0087423906 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -125,6 +125,8 @@ class SalesInvoice(SellingController): self.validate_multiple_billing("Delivery Note", "dn_detail", "amount", "items") if not self.is_return: self.validate_serial_numbers() + else: + self.timesheets = [] self.update_packing_list() self.set_billing_hours_and_amount() self.update_timesheet_billing_for_project() @@ -337,7 +339,7 @@ class SalesInvoice(SellingController): if "Healthcare" in active_domains: manage_invoice_submit_cancel(self, "on_cancel") - + self.unlink_sales_invoice_from_timesheets() self.ignore_linked_doctypes = ('GL Entry', 'Stock Ledger Entry', 'Repost Item Valuation') def update_status_updater_args(self): @@ -393,6 +395,18 @@ class SalesInvoice(SellingController): if validate_against_credit_limit: check_credit_limit(self.customer, self.company, bypass_credit_limit_check_at_sales_order) + def unlink_sales_invoice_from_timesheets(self): + for row in self.timesheets: + timesheet = frappe.get_doc('Timesheet', row.time_sheet) + for time_log in timesheet.time_logs: + if time_log.sales_invoice == self.name: + time_log.sales_invoice = None + timesheet.calculate_total_amounts() + timesheet.calculate_percentage_billed() + timesheet.flags.ignore_validate_update_after_submit = True + timesheet.set_status() + timesheet.db_update_all() + @frappe.whitelist() def set_missing_values(self, for_validate=False): pos = self.set_pos_fields(for_validate) @@ -427,7 +441,7 @@ class SalesInvoice(SellingController): timesheet.calculate_percentage_billed() timesheet.flags.ignore_validate_update_after_submit = True timesheet.set_status() - timesheet.save() + timesheet.db_update_all() def update_time_sheet_detail(self, timesheet, args, sales_invoice): for data in timesheet.time_logs: @@ -741,8 +755,10 @@ class SalesInvoice(SellingController): self.append('timesheets', { 'time_sheet': data.parent, 'billing_hours': data.billing_hours, - 'billing_amount': data.billing_amt, - 'timesheet_detail': data.name + 'billing_amount': data.billing_amount, + 'timesheet_detail': data.name, + 'activity_type': data.activity_type, + 'description': data.description }) self.calculate_billing_amount_for_timesheet() diff --git a/erpnext/accounts/doctype/sales_invoice_timesheet/sales_invoice_timesheet.json b/erpnext/accounts/doctype/sales_invoice_timesheet/sales_invoice_timesheet.json index f7b9aef96cc..9321630829c 100644 --- a/erpnext/accounts/doctype/sales_invoice_timesheet/sales_invoice_timesheet.json +++ b/erpnext/accounts/doctype/sales_invoice_timesheet/sales_invoice_timesheet.json @@ -1,172 +1,77 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "beta": 0, - "creation": "2016-06-14 19:21:34.321662", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 1, - "engine": "InnoDB", + "actions": [], + "creation": "2016-06-14 19:21:34.321662", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "activity_type", + "description", + "billing_hours", + "billing_amount", + "time_sheet", + "timesheet_detail" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "time_sheet", - "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": "Time Sheet", - "length": 0, - "no_copy": 0, - "options": "Timesheet", - "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 - }, + "fieldname": "time_sheet", + "fieldtype": "Link", + "in_global_search": 1, + "in_list_view": 1, + "label": "Time Sheet", + "options": "Timesheet", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "billing_hours", - "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": "Billing Hours", - "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 - }, + "fieldname": "billing_hours", + "fieldtype": "Float", + "in_list_view": 1, + "label": "Billing Hours", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "billing_amount", - "fieldtype": "Currency", - "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": "Billing Amount", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "billing_amount", + "fieldtype": "Currency", + "in_list_view": 1, + "label": "Billing Amount", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "timesheet_detail", - "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": "Timesheet Detail", - "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_on_submit": 1, + "fieldname": "timesheet_detail", + "fieldtype": "Data", + "hidden": 1, + "label": "Timesheet Detail", + "no_copy": 1, + "print_hide": 1, + "read_only": 1 + }, + { + "fieldname": "activity_type", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Activity Type", + "options": "Activity Type", + "read_only": 1 + }, + { + "fieldname": "description", + "fieldtype": "Small Text", + "in_list_view": 1, + "label": "Description", + "read_only": 1 } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 1, - "max_attachments": 0, - "modified": "2019-02-18 18:50:44.770361", - "modified_by": "Administrator", - "module": "Accounts", - "name": "Sales Invoice Timesheet", - "name_case": "", - "owner": "Administrator", - "permissions": [], - "quick_entry": 1, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 1, - "track_seen": 0, - "track_views": 0 + ], + "istable": 1, + "links": [], + "modified": "2021-05-13 16:52:32.995266", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Sales Invoice Timesheet", + "owner": "Administrator", + "permissions": [], + "quick_entry": 1, + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 } \ No newline at end of file diff --git a/erpnext/hooks.py b/erpnext/hooks.py index bb6cd8bdc2b..ca8ca871bdc 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -304,7 +304,8 @@ doc_events = { # if payment entry not in auto cancel exempted doctypes it will cancel payment entry. auto_cancel_exempted_doctypes= [ "Payment Entry", - "Inpatient Medication Entry" + "Inpatient Medication Entry", + "Timesheet" ] after_migrate = ["erpnext.setup.install.update_select_perm_after_install"] diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 82d223cada0..cec2dd5341a 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -778,3 +778,4 @@ erpnext.patches.v12_0.add_ewaybill_validity_field erpnext.patches.v13_0.germany_make_custom_fields erpnext.patches.v13_0.germany_fill_debtor_creditor_number erpnext.patches.v13_0.set_pos_closing_as_failed +erpnext.patches.v13_0.rename_billable_to_is_billable_in_timesheet diff --git a/erpnext/patches/v7_0/convert_timelog_to_timesheet.py b/erpnext/patches/v7_0/convert_timelog_to_timesheet.py index 3af6622d96e..8c60b5b71ec 100644 --- a/erpnext/patches/v7_0/convert_timelog_to_timesheet.py +++ b/erpnext/patches/v7_0/convert_timelog_to_timesheet.py @@ -51,7 +51,7 @@ def execute(): def get_timelog_data(data): return { - 'billable': data.billable, + 'is_billable': data.billable, 'from_time': data.from_time, 'hours': data.hours, 'to_time': data.to_time, diff --git a/erpnext/projects/doctype/timesheet/test_timesheet.py b/erpnext/projects/doctype/timesheet/test_timesheet.py index d21ac0f2f02..2b0c3abdd77 100644 --- a/erpnext/projects/doctype/timesheet/test_timesheet.py +++ b/erpnext/projects/doctype/timesheet/test_timesheet.py @@ -37,7 +37,7 @@ class TestTimesheet(unittest.TestCase): emp = make_employee("test_employee_6@salary.com") make_salary_structure_for_timesheet(emp) - timesheet = make_timesheet(emp, simulate=True, billable=1) + timesheet = make_timesheet(emp, simulate=True, is_billable=1) self.assertEqual(timesheet.total_hours, 2) self.assertEqual(timesheet.total_billable_hours, 2) @@ -49,7 +49,7 @@ class TestTimesheet(unittest.TestCase): emp = make_employee("test_employee_6@salary.com") make_salary_structure_for_timesheet(emp) - timesheet = make_timesheet(emp, simulate=True, billable=0) + timesheet = make_timesheet(emp, simulate=True, is_billable=0) self.assertEqual(timesheet.total_hours, 2) self.assertEqual(timesheet.total_billable_hours, 0) @@ -61,7 +61,7 @@ class TestTimesheet(unittest.TestCase): emp = make_employee("test_employee_6@salary.com", company="_Test Company") salary_structure = make_salary_structure_for_timesheet(emp) - timesheet = make_timesheet(emp, simulate = True, billable=1) + timesheet = make_timesheet(emp, simulate = True, is_billable=1) salary_slip = make_salary_slip(timesheet.name) salary_slip.submit() @@ -82,7 +82,7 @@ class TestTimesheet(unittest.TestCase): def test_sales_invoice_from_timesheet(self): emp = make_employee("test_employee_6@salary.com") - timesheet = make_timesheet(emp, simulate=True, billable=1) + timesheet = make_timesheet(emp, simulate=True, is_billable=1) sales_invoice = make_sales_invoice(timesheet.name, '_Test Item', '_Test Customer') sales_invoice.due_date = nowdate() sales_invoice.submit() @@ -100,7 +100,7 @@ class TestTimesheet(unittest.TestCase): emp = make_employee("test_employee_6@salary.com") project = frappe.get_value("Project", {"project_name": "_Test Project"}) - timesheet = make_timesheet(emp, simulate=True, billable=1, project=project, company='_Test Company') + timesheet = make_timesheet(emp, simulate=True, is_billable=1, project=project, company='_Test Company') sales_invoice = create_sales_invoice(do_not_save=True) sales_invoice.project = project sales_invoice.submit() @@ -171,13 +171,13 @@ def make_salary_structure_for_timesheet(employee, company=None): return salary_structure -def make_timesheet(employee, simulate=False, billable = 0, activity_type="_Test Activity Type", project=None, task=None, company=None): +def make_timesheet(employee, simulate=False, is_billable = 0, activity_type="_Test Activity Type", project=None, task=None, company=None): update_activity_type(activity_type) timesheet = frappe.new_doc("Timesheet") timesheet.employee = employee timesheet.company = company or '_Test Company' timesheet_detail = timesheet.append('time_logs', {}) - timesheet_detail.billable = billable + timesheet_detail.is_billable = is_billable timesheet_detail.activity_type = activity_type timesheet_detail.from_time = now_datetime() timesheet_detail.hours = 2 diff --git a/erpnext/projects/doctype/timesheet/timesheet.js b/erpnext/projects/doctype/timesheet/timesheet.js index b123af5d188..5554ed9264c 100644 --- a/erpnext/projects/doctype/timesheet/timesheet.js +++ b/erpnext/projects/doctype/timesheet/timesheet.js @@ -90,17 +90,50 @@ frappe.ui.form.on("Timesheet", { } if(frm.doc.per_billed > 0) { frm.fields_dict["time_logs"].grid.toggle_enable("billing_hours", false); - frm.fields_dict["time_logs"].grid.toggle_enable("billable", false); + frm.fields_dict["time_logs"].grid.toggle_enable("is_billable", false); } + frm.trigger('setup_filters'); + }, + + customer: function(frm) { + frm.set_query('parent_project', function(doc) { + return { + filters: { + "customer": doc.customer + } + }; + }); + frm.set_query('project', 'time_logs', function(doc) { + return { + filters: { + "customer": doc.customer + } + }; + }); + frm.refresh(); }, make_invoice: function(frm) { + let fields = [{ + "fieldtype": "Link", + "label": __("Item Code"), + "fieldname": "item_code", + "options": "Item" + }] + + if (!frm.doc.customer) { + fields.push({ + "fieldtype": "Link", + "label": __("Customer"), + "fieldname": "customer", + "options": "Customer", + "default": frm.doc.customer + }); + } + let dialog = new frappe.ui.Dialog({ - title: __("Select Item (optional)"), - fields: [ - {"fieldtype": "Link", "label": __("Item Code"), "fieldname": "item_code", "options":"Item"}, - {"fieldtype": "Link", "label": __("Customer"), "fieldname": "customer", "options":"Customer"} - ] + title: __("Create Sales Invoice"), + fields: fields }); dialog.set_primary_action(__('Create Sales Invoice'), () => { @@ -113,7 +146,8 @@ frappe.ui.form.on("Timesheet", { args: { "source_name": frm.doc.name, "item_code": args.item_code, - "customer": args.customer + "customer": frm.doc.customer || args.customer, + "currency": frm.doc.currency }, freeze: true, callback: function(r) { @@ -136,8 +170,7 @@ frappe.ui.form.on("Timesheet", { parent_project: function(frm) { set_project_in_timelog(frm); - }, - + } }); frappe.ui.form.on("Timesheet Detail", { @@ -196,7 +229,7 @@ frappe.ui.form.on("Timesheet Detail", { calculate_billing_costing_amount(frm, cdt, cdn); }, - billable: function(frm, cdt, cdn) { + is_billable: function(frm, cdt, cdn) { update_billing_hours(frm, cdt, cdn); update_time_rates(frm, cdt, cdn); calculate_billing_costing_amount(frm, cdt, cdn); @@ -239,9 +272,9 @@ var calculate_end_time = function(frm, cdt, cdn) { } }; -var update_billing_hours = function(frm, cdt, cdn){ - var child = locals[cdt][cdn]; - if(!child.billable) { +var update_billing_hours = function(frm, cdt, cdn) { + let child = frappe.get_doc(cdt, cdn); + if (!child.is_billable) { frappe.model.set_value(cdt, cdn, 'billing_hours', 0.0); } else { // bill all hours by default @@ -249,19 +282,19 @@ var update_billing_hours = function(frm, cdt, cdn){ } }; -var update_time_rates = function(frm, cdt, cdn){ - var child = locals[cdt][cdn]; - if(!child.billable){ +var update_time_rates = function(frm, cdt, cdn) { + let child = frappe.get_doc(cdt, cdn); + if (!child.is_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]; - var billing_amount = 0.0; - var costing_amount = 0.0; +var calculate_billing_costing_amount = function(frm, cdt, cdn) { + let child = frappe.get_doc(cdt, cdn); + let billing_amount = 0.0; + let costing_amount = 0.0; - if(child.billing_hours && child.billable){ + if (child.billing_hours && child.is_billable) { billing_amount = (child.billing_hours * child.billing_rate); } costing_amount = flt(child.costing_rate * child.hours); @@ -271,18 +304,18 @@ var calculate_billing_costing_amount = function(frm, cdt, cdn){ }; var calculate_time_and_amount = function(frm) { - var tl = frm.doc.time_logs || []; - var total_working_hr = 0; - var total_billing_hr = 0; - var total_billable_amount = 0; - var total_costing_amount = 0; + let tl = frm.doc.time_logs || []; + let total_working_hr = 0; + let total_billing_hr = 0; + let total_billable_amount = 0; + let total_costing_amount = 0; for(var i=0; i Date: Sat, 15 May 2021 20:40:20 +0530 Subject: [PATCH 027/135] adding patch --- .../v13_0/rename_billable_to_is_billable_in_timesheet.py | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 erpnext/patches/v13_0/rename_billable_to_is_billable_in_timesheet.py diff --git a/erpnext/patches/v13_0/rename_billable_to_is_billable_in_timesheet.py b/erpnext/patches/v13_0/rename_billable_to_is_billable_in_timesheet.py new file mode 100644 index 00000000000..6860a37559e --- /dev/null +++ b/erpnext/patches/v13_0/rename_billable_to_is_billable_in_timesheet.py @@ -0,0 +1,7 @@ +from __future__ import unicode_literals +import frappe +from frappe.model.utils.rename_field import rename_field + +def execute(): + if "billable" in frappe.db.get_table_columns("Timesheet Detail"): + rename_field("Timesheet Detail", "billable", "is_billable") \ No newline at end of file From 42d2f663fa9f22542b2ef29a39f667774d56a907 Mon Sep 17 00:00:00 2001 From: Anupam Date: Mon, 17 May 2021 11:08:26 +0530 Subject: [PATCH 028/135] fix: sider fixes --- erpnext/projects/doctype/timesheet/timesheet.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/projects/doctype/timesheet/timesheet.js b/erpnext/projects/doctype/timesheet/timesheet.js index 5554ed9264c..28535d7a342 100644 --- a/erpnext/projects/doctype/timesheet/timesheet.js +++ b/erpnext/projects/doctype/timesheet/timesheet.js @@ -119,7 +119,7 @@ frappe.ui.form.on("Timesheet", { "label": __("Item Code"), "fieldname": "item_code", "options": "Item" - }] + }]; if (!frm.doc.customer) { fields.push({ From 41ac8be6f20c490c2700de884257314a07a6ba63 Mon Sep 17 00:00:00 2001 From: noahjacob Date: Mon, 17 May 2021 13:58:27 +0530 Subject: [PATCH 029/135] refactor: base_amount field moved below amount field and renamed --- .../landed_cost_taxes_and_charges.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/erpnext/stock/doctype/landed_cost_taxes_and_charges/landed_cost_taxes_and_charges.json b/erpnext/stock/doctype/landed_cost_taxes_and_charges/landed_cost_taxes_and_charges.json index 4fcdb4c10cc..9c59c13ac07 100644 --- a/erpnext/stock/doctype/landed_cost_taxes_and_charges/landed_cost_taxes_and_charges.json +++ b/erpnext/stock/doctype/landed_cost_taxes_and_charges/landed_cost_taxes_and_charges.json @@ -10,8 +10,8 @@ "exchange_rate", "description", "col_break3", - "base_amount", - "amount" + "amount", + "base_amount" ], "fields": [ { @@ -59,7 +59,7 @@ { "fieldname": "base_amount", "fieldtype": "Currency", - "label": "Base Amount", + "label": "Amount (Company Currency)", "options": "Company:company:default_currency", "read_only": 1 } @@ -67,7 +67,7 @@ "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2020-12-26 01:07:23.233604", + "modified": "2021-05-17 13:57:10.807980", "modified_by": "Administrator", "module": "Stock", "name": "Landed Cost Taxes and Charges", From f3b3d81e0bba3996c11b8e5aa93a2aec3a04ac5b Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Mon, 17 May 2021 16:43:38 +0530 Subject: [PATCH 030/135] fix: escape company name in deferred_revenue --- erpnext/accounts/deferred_revenue.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/deferred_revenue.py b/erpnext/accounts/deferred_revenue.py index d5ab1c17042..0f47b953aff 100644 --- a/erpnext/accounts/deferred_revenue.py +++ b/erpnext/accounts/deferred_revenue.py @@ -41,7 +41,7 @@ def build_conditions(process_type, account, company): if account: conditions += "AND %s='%s'"%(deferred_account, account) elif company: - conditions += "AND p.company='%s'"%(company) + conditions += f"AND p.company = {frappe.db.escape(company)}" return conditions From b6783b158f1f4346fb5fab3a9f0110e91bdff221 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Mon, 17 May 2021 17:06:12 +0530 Subject: [PATCH 031/135] chore: translation fixes --- erpnext/accounts/deferred_revenue.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/erpnext/accounts/deferred_revenue.py b/erpnext/accounts/deferred_revenue.py index 0f47b953aff..dd346bc2408 100644 --- a/erpnext/accounts/deferred_revenue.py +++ b/erpnext/accounts/deferred_revenue.py @@ -360,12 +360,10 @@ def make_gl_entries(doc, credit_account, debit_account, against, frappe.flags.deferred_accounting_error = True def send_mail(deferred_process): - title = _("Error while processing deferred accounting for {0}".format(deferred_process)) - content = _(""" - Deferred accounting failed for some invoices: - Please check Process Deferred Accounting {0} - and submit manually after resolving errors - """).format(get_link_to_form('Process Deferred Accounting', deferred_process)) + title = _("Error while processing deferred accounting for {0}").format(deferred_process) + link = get_link_to_form('Process Deferred Accounting', deferred_process) + content = _("Deferred accounting failed for some invoices:") + "\n" + content += _("Please check Process Deferred Accounting {0} and submit manually after resolving errors.").format(link) sendmail_to_system_managers(title, content) def book_revenue_via_journal_entry(doc, credit_account, debit_account, against, From ca2fb47d445a6cfeacf67fcd5538ed385105dd83 Mon Sep 17 00:00:00 2001 From: noahjacob Date: Wed, 12 May 2021 16:25:07 +0530 Subject: [PATCH 032/135] feat: updates item_code filters if item_group is linked to supplier --- erpnext/controllers/queries.py | 15 +++++++++++++-- erpnext/public/js/controllers/buying.js | 4 ++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py index bc1ac5ea069..e71b056c6e2 100644 --- a/erpnext/controllers/queries.py +++ b/erpnext/controllers/queries.py @@ -204,7 +204,7 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals if "description" in searchfields: searchfields.remove("description") - + columns = '' extra_searchfields = [field for field in searchfields if not field in ["name", "item_group", "description"]] @@ -216,11 +216,22 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals if not field in searchfields] searchfields = " or ".join([field + " like %(txt)s" for field in searchfields]) + if filters.get('supplier'): + item_group_list = frappe.get_list('Supplier Item Group', filters = {'supplier': filters.get('supplier')}, fields = ['item_group']) + + item_groups = [] + for i in item_group_list: + item_groups.append(i.item_group) + + del filters['supplier'] + + if item_groups: + filters['item_group'] = ['in', item_groups] + description_cond = '' if frappe.db.count('Item', cache=True) < 50000: # scan description only if items are less than 50000 description_cond = 'or tabItem.description LIKE %(txt)s' - return frappe.db.sql("""select tabItem.name, if(length(tabItem.item_name) > 40, concat(substr(tabItem.item_name, 1, 40), "..."), item_name) as item_name, diff --git a/erpnext/public/js/controllers/buying.js b/erpnext/public/js/controllers/buying.js index cdfd909b046..e7dcd410682 100644 --- a/erpnext/public/js/controllers/buying.js +++ b/erpnext/public/js/controllers/buying.js @@ -84,13 +84,13 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({ if (me.frm.doc.is_subcontracted == "Yes") { return{ query: "erpnext.controllers.queries.item_query", - filters:{ 'is_sub_contracted_item': 1 } + filters:{ 'supplier': me.frm.doc.supplier, 'is_sub_contracted_item': 1 } } } else { return{ query: "erpnext.controllers.queries.item_query", - filters: {'is_purchase_item': 1} + filters: { 'supplier': me.frm.doc.supplier, 'is_purchase_item': 1 } } } }); From 0ab0fcdd51cd4b982c67518217d5ca77fa4ea4f0 Mon Sep 17 00:00:00 2001 From: noahjacob Date: Tue, 18 May 2021 15:21:24 +0530 Subject: [PATCH 033/135] feat: added supplier item group link in supplier dashboard --- erpnext/buying/doctype/supplier/supplier.json | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/erpnext/buying/doctype/supplier/supplier.json b/erpnext/buying/doctype/supplier/supplier.json index 4cc5753cbd0..38b8dfdf48d 100644 --- a/erpnext/buying/doctype/supplier/supplier.json +++ b/erpnext/buying/doctype/supplier/supplier.json @@ -383,8 +383,14 @@ "icon": "fa fa-user", "idx": 370, "image_field": "image", - "links": [], - "modified": "2021-01-06 19:51:40.939087", + "links": [ + { + "group": "Item Group", + "link_doctype": "Supplier Item Group", + "link_fieldname": "supplier" + } + ], + "modified": "2021-05-18 15:10:11.087191", "modified_by": "Administrator", "module": "Buying", "name": "Supplier", From 60ea785dfd434f67112e785b8a4bcb4e7705ee03 Mon Sep 17 00:00:00 2001 From: prssanna Date: Tue, 18 May 2021 15:42:13 +0530 Subject: [PATCH 034/135] fix: ensure website theme is applied correctly --- erpnext/public/scss/shopping_cart.scss | 18 +++++++++--------- erpnext/public/scss/website.scss | 9 ++++----- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/erpnext/public/scss/shopping_cart.scss b/erpnext/public/scss/shopping_cart.scss index 159a8a47cd3..92e5d32219e 100644 --- a/erpnext/public/scss/shopping_cart.scss +++ b/erpnext/public/scss/shopping_cart.scss @@ -1,4 +1,3 @@ -@import "frappe/public/scss/desk/variables"; @import "frappe/public/scss/common/mixins"; body.product-page { @@ -217,12 +216,12 @@ body.product-page { border-color: var(--table-border-color) !important; padding: 15px; - @include media-breakpoint-between(xs, md) { + @media (max-width: 840px) { height: 300px; width: 300px; } - @include media-breakpoint-up(lg) { + @media (min-width: 1090px) { height: 350px; width: 350px; } @@ -233,11 +232,12 @@ body.product-page { } .item-slideshow { - @include media-breakpoint-between(xs, md) { + + @media (max-width: 840px) { max-height: 320px; } - @include media-breakpoint-up(lg) { + @media (min-width: 1090px) { max-height: 430px; } @@ -254,7 +254,7 @@ body.product-page { cursor: pointer; &:hover, &.active { - border-color: $primary; + border-color: var(--primary); } } @@ -316,12 +316,12 @@ body.product-page { } .item-group-slideshow { - .item-group-description { + // .item-group-description { // max-width: 900px; - } + // } .carousel-inner.rounded-carousel { - border-radius: $card-border-radius; + border-radius: var(--card-border-radius); } } diff --git a/erpnext/public/scss/website.scss b/erpnext/public/scss/website.scss index 56b717c4240..f4325c03f5b 100644 --- a/erpnext/public/scss/website.scss +++ b/erpnext/public/scss/website.scss @@ -1,4 +1,3 @@ -@import "frappe/public/scss/website/variables"; .filter-options { max-height: 300px; @@ -14,7 +13,7 @@ } &.active { - border-color: $primary; + border-color: var(--primary); .check { display: inline-flex; @@ -25,7 +24,7 @@ .check { display: inline-flex; padding: 0.25rem; - background: $primary; + background: var(--primary); color: white; border-radius: 50%; font-size: 12px; @@ -38,12 +37,12 @@ } .result { - border-bottom: 1px solid $border-color; + border-bottom: 1px solid var(--border-color); } .transaction-list-item { padding: 1rem 0; - border-top: 1px solid $border-color; + border-top: 1px solid var(--border-color); position: relative; a.transaction-item-link { From bdba064fa6f76a98d5d0d7822c7648a6f24d8491 Mon Sep 17 00:00:00 2001 From: Devin Slauenwhite Date: Tue, 18 May 2021 06:42:53 -0400 Subject: [PATCH 035/135] fix: duplicate stock entry (#25486) Co-authored-by: Ankush Menat --- erpnext/stock/dashboard/item_dashboard.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/stock/dashboard/item_dashboard.js b/erpnext/stock/dashboard/item_dashboard.js index 933ca8ab3d4..db0573954fa 100644 --- a/erpnext/stock/dashboard/item_dashboard.js +++ b/erpnext/stock/dashboard/item_dashboard.js @@ -230,6 +230,7 @@ erpnext.stock.move_item = function (item, source, target, actual_qty, rate, call }, ], }); + var submitted = false; dialog.show(); dialog.get_field('item_code').set_input(item); @@ -253,6 +254,7 @@ erpnext.stock.move_item = function (item, source, target, actual_qty, rate, call } dialog.set_primary_action(__('Submit'), function () { + if(submitted) return; var values = dialog.get_values(); if (!values) { return; @@ -265,6 +267,7 @@ erpnext.stock.move_item = function (item, source, target, actual_qty, rate, call frappe.msgprint(__('Source and target warehouse must be different')); } + submitted = true; frappe.call({ method: 'erpnext.stock.doctype.stock_entry.stock_entry_utils.make_stock_entry', args: values, From 042b8524ccb25b0930313fd13fbf2844c2ac5341 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Tue, 18 May 2021 16:31:55 +0530 Subject: [PATCH 036/135] fix: disable submit button to avoid multiple calls --- erpnext/stock/dashboard/item_dashboard.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erpnext/stock/dashboard/item_dashboard.js b/erpnext/stock/dashboard/item_dashboard.js index db0573954fa..dfb9e44283c 100644 --- a/erpnext/stock/dashboard/item_dashboard.js +++ b/erpnext/stock/dashboard/item_dashboard.js @@ -271,7 +271,9 @@ erpnext.stock.move_item = function (item, source, target, actual_qty, rate, call frappe.call({ method: 'erpnext.stock.doctype.stock_entry.stock_entry_utils.make_stock_entry', args: values, + btn: dialog.get_primary_btn(), freeze: true, + freeze_message: __('Creating Stock Entry'), callback: function (r) { frappe.show_alert(__('Stock Entry {0} created', ['' + r.message.name + ''])); From ecbb8cbc844ca451b76fb0fa4fdc30fd7592aad2 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Tue, 18 May 2021 16:33:15 +0530 Subject: [PATCH 037/135] revert: "fix: duplicate stock entry (#25486)" Not required anymore, submit button is disabled. --- erpnext/stock/dashboard/item_dashboard.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/erpnext/stock/dashboard/item_dashboard.js b/erpnext/stock/dashboard/item_dashboard.js index dfb9e44283c..a657ecf1055 100644 --- a/erpnext/stock/dashboard/item_dashboard.js +++ b/erpnext/stock/dashboard/item_dashboard.js @@ -230,7 +230,6 @@ erpnext.stock.move_item = function (item, source, target, actual_qty, rate, call }, ], }); - var submitted = false; dialog.show(); dialog.get_field('item_code').set_input(item); @@ -254,7 +253,6 @@ erpnext.stock.move_item = function (item, source, target, actual_qty, rate, call } dialog.set_primary_action(__('Submit'), function () { - if(submitted) return; var values = dialog.get_values(); if (!values) { return; @@ -267,7 +265,6 @@ erpnext.stock.move_item = function (item, source, target, actual_qty, rate, call frappe.msgprint(__('Source and target warehouse must be different')); } - submitted = true; frappe.call({ method: 'erpnext.stock.doctype.stock_entry.stock_entry_utils.make_stock_entry', args: values, From 426b04003cba3935ca1bf4f369f9f4b8b2ffed84 Mon Sep 17 00:00:00 2001 From: Syed Mujeer Hashmi Date: Sat, 15 May 2021 12:12:26 +0530 Subject: [PATCH 038/135] fix: Project filter for Kanban Board Signed-off-by: Syed Mujeer Hashmi --- erpnext/projects/doctype/project/project.js | 2 +- erpnext/projects/doctype/project/project.py | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/erpnext/projects/doctype/project/project.js b/erpnext/projects/doctype/project/project.js index c5265e23c0a..31460f66ea3 100644 --- a/erpnext/projects/doctype/project/project.js +++ b/erpnext/projects/doctype/project/project.js @@ -87,7 +87,7 @@ frappe.ui.form.on("Project", { frm.add_custom_button(__("Kanban Board"), () => { frappe.call('erpnext.projects.doctype.project.project.create_kanban_board_if_not_exists', { - project: frm.doc.project_name + project: frm.doc.name }).then(() => { frappe.set_route('List', 'Task', 'Kanban', frm.doc.project_name); }); diff --git a/erpnext/projects/doctype/project/project.py b/erpnext/projects/doctype/project/project.py index 55c5149a9cc..c8fbe0bf7be 100644 --- a/erpnext/projects/doctype/project/project.py +++ b/erpnext/projects/doctype/project/project.py @@ -523,8 +523,9 @@ def update_project_sales_billing(): def create_kanban_board_if_not_exists(project): from frappe.desk.doctype.kanban_board.kanban_board import quick_kanban_board - if not frappe.db.exists('Kanban Board', project): - quick_kanban_board('Task', project, 'status', project) + project = frappe.get_doc('Project', project) + if not frappe.db.exists('Kanban Board', project.project_name): + quick_kanban_board('Task', project.project_name, 'status', project.name) return True From 8d7d4b0ba7d92551957505923f57eef0e47a2840 Mon Sep 17 00:00:00 2001 From: Saqib Date: Tue, 18 May 2021 18:39:35 +0530 Subject: [PATCH 039/135] fix: expected amount in pos closing payments table (#25737) --- .../pos_closing_entry/pos_closing_entry.js | 39 ++++++++++++------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.js b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.js index aa0c53e228b..8c5a34a0d8e 100644 --- a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.js +++ b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.js @@ -101,15 +101,24 @@ frappe.ui.form.on('POS Closing Entry', { }, before_save: function(frm) { + frm.set_value("grand_total", 0); + frm.set_value("net_total", 0); + frm.set_value("total_quantity", 0); + frm.set_value("taxes", []); + + for (let row of frm.doc.payment_reconciliation) { + row.expected_amount = 0; + } + for (let row of frm.doc.pos_transactions) { frappe.db.get_doc("POS Invoice", row.pos_invoice).then(doc => { - cur_frm.doc.grand_total -= flt(doc.grand_total); - cur_frm.doc.net_total -= flt(doc.net_total); - cur_frm.doc.total_quantity -= flt(doc.total_qty); - refresh_payments(doc, cur_frm, 1); - refresh_taxes(doc, cur_frm, 1); - refresh_fields(cur_frm); - set_html_data(cur_frm); + frm.doc.grand_total += flt(doc.grand_total); + frm.doc.net_total += flt(doc.net_total); + frm.doc.total_quantity += flt(doc.total_qty); + refresh_payments(doc, frm); + refresh_taxes(doc, frm); + refresh_fields(frm); + set_html_data(frm); }); } } @@ -118,7 +127,7 @@ frappe.ui.form.on('POS Closing Entry', { frappe.ui.form.on('POS Closing Entry Detail', { closing_amount: (frm, cdt, cdn) => { const row = locals[cdt][cdn]; - frappe.model.set_value(cdt, cdn, "difference", flt(row.expected_amount - row.closing_amount)) + frappe.model.set_value(cdt, cdn, "difference", flt(row.expected_amount - row.closing_amount)); } }) @@ -142,28 +151,28 @@ function add_to_pos_transaction(d, frm) { }) } -function refresh_payments(d, frm, remove) { +function refresh_payments(d, frm) { d.payments.forEach(p => { const payment = frm.doc.payment_reconciliation.find(pay => pay.mode_of_payment === p.mode_of_payment); if (payment) { - if (!remove) payment.expected_amount += flt(p.amount); - else payment.expected_amount -= flt(p.amount); + payment.expected_amount += flt(p.amount); + payment.difference = payment.closing_amount - payment.expected_amount; } else { frm.add_child("payment_reconciliation", { mode_of_payment: p.mode_of_payment, opening_amount: 0, - expected_amount: p.amount + expected_amount: p.amount, + closing_amount: 0 }) } }) } -function refresh_taxes(d, frm, remove) { +function refresh_taxes(d, frm) { d.taxes.forEach(t => { const tax = frm.doc.taxes.find(tx => tx.account_head === t.account_head && tx.rate === t.rate); if (tax) { - if (!remove) tax.amount += flt(t.tax_amount); - else tax.amount -= flt(t.tax_amount); + tax.amount += flt(t.tax_amount); } else { frm.add_child("taxes", { account_head: t.account_head, From 90f7ec840cf97ffdc8c523a33f3c3ba667eb7b0e Mon Sep 17 00:00:00 2001 From: anushka19 <37659765+anushka19@users.noreply.github.com> Date: Tue, 18 May 2021 22:21:42 +0530 Subject: [PATCH 040/135] fix: Accumulated depreciation (#25748) * fix: Accumulated depreciation * fix: Sider issues --- erpnext/assets/doctype/asset_category/asset_category.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/assets/doctype/asset_category/asset_category.js b/erpnext/assets/doctype/asset_category/asset_category.js index 74963c2aa96..51ce157a81c 100644 --- a/erpnext/assets/doctype/asset_category/asset_category.js +++ b/erpnext/assets/doctype/asset_category/asset_category.js @@ -4,7 +4,7 @@ frappe.ui.form.on('Asset Category', { onload: function(frm) { frm.add_fetch('company_name', 'accumulated_depreciation_account', 'accumulated_depreciation_account'); - frm.add_fetch('company_name', 'depreciation_expense_account', 'accumulated_depreciation_account'); + frm.add_fetch('company_name', 'depreciation_expense_account', 'depreciation_expense_account'); frm.set_query('fixed_asset_account', 'accounts', function(doc, cdt, cdn) { var d = locals[cdt][cdn]; From 9bd779401d23902d161c70502ce091548989a37e Mon Sep 17 00:00:00 2001 From: Anupam Date: Tue, 18 May 2021 22:41:28 +0530 Subject: [PATCH 041/135] added multi-currency fields --- .../doctype/activity_type/activity_type.js | 4 + .../projects/doctype/timesheet/timesheet.js | 81 +++++++++++++++---- .../projects/doctype/timesheet/timesheet.py | 17 +++- .../timesheet_detail/timesheet_detail.json | 36 ++++++++- 4 files changed, 115 insertions(+), 23 deletions(-) diff --git a/erpnext/projects/doctype/activity_type/activity_type.js b/erpnext/projects/doctype/activity_type/activity_type.js index 7eb3571af10..f1ba882812e 100644 --- a/erpnext/projects/doctype/activity_type/activity_type.js +++ b/erpnext/projects/doctype/activity_type/activity_type.js @@ -1,4 +1,8 @@ frappe.ui.form.on("Activity Type", { + onload: function(frm) { + frm.set_currency_labels(["billing_rate", "costing_rate"], frappe.defaults.get_global_default('currency')); + }, + refresh: function(frm) { frm.add_custom_button(__("Activity Cost per Employee"), function() { frappe.route_options = {"activity_type": frm.doc.name}; diff --git a/erpnext/projects/doctype/timesheet/timesheet.js b/erpnext/projects/doctype/timesheet/timesheet.js index 28535d7a342..532d64994f1 100644 --- a/erpnext/projects/doctype/timesheet/timesheet.js +++ b/erpnext/projects/doctype/timesheet/timesheet.js @@ -93,6 +93,7 @@ frappe.ui.form.on("Timesheet", { frm.fields_dict["time_logs"].grid.toggle_enable("is_billable", false); } frm.trigger('setup_filters'); + frm.trigger('set_dynamic_field_label'); }, customer: function(frm) { @@ -113,6 +114,48 @@ frappe.ui.form.on("Timesheet", { frm.refresh(); }, + currency: function(frm) { + let base_currency = frappe.defaults.get_global_default('currency'); + if (base_currency != frm.doc.company) { + frappe.call({ + method: "erpnext.setup.utils.get_exchange_rate", + args: { + from_currency: frm.doc.currency, + to_currency: base_currency + }, + callback: function(r) { + if (r.message) { + frm.set_value('exchange_rate', flt(r.message)); + frm.set_df_property("exchange_rate", "description", "1 " + frm.doc.currency + " = [?] " + base_currency); + } + } + }); + } + frm.trigger('set_dynamic_field_label'); + }, + + exchange_rate: function(frm) { + $.each(frm.doc.time_logs, function(i, d) { + calculate_billing_costing_amount(frm, d.doctype, d.name); + }); + calculate_time_and_amount(frm); + }, + + set_dynamic_field_label: function(frm) { + let base_currency = frappe.defaults.get_global_default('currency'); + frm.set_currency_labels(["base_total_costing_amount", "base_total_billable_amount", "base_total_billed_amount"], base_currency); + frm.set_currency_labels(["total_costing_amount", "total_billable_amount", "total_billed_amount"], frm.doc.currency); + frm.set_currency_labels(["base_billing_rate", "base_billing_amount", "base_costing_rate", "base_costing_amount"], base_currency, "time_logs"); + frm.set_currency_labels(["billing_rate", "billing_amount", "costing_rate", "costing_amount"], frm.doc.currency, "time_logs"); + + let time_logs_grid = frm.fields_dict.time_logs.grid; + $.each(["base_billing_rate", "base_billing_amount", "base_costing_rate", "base_costing_amount"], function(i, d) { + if(frappe.meta.get_docfield(time_logs_grid.doctype, d)) + time_logs_grid.set_column_disp(d, frm.doc.currency != base_currency); + }); + frm.refresh_fields(); + }, + make_invoice: function(frm) { let fields = [{ "fieldtype": "Link", @@ -204,35 +247,34 @@ frappe.ui.form.on("Timesheet Detail", { if(frm.doc.parent_project) { frappe.model.set_value(cdt, cdn, 'project', frm.doc.parent_project); } - - var $trigger_again = $('.form-grid').find('.grid-row').find('.btn-open-row'); - $trigger_again.on('click', () => { - $('.form-grid') - .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_billing_costing_amount(frm, cdt, cdn); + calculate_time_and_amount(frm); }, billing_hours: function(frm, cdt, cdn) { calculate_billing_costing_amount(frm, cdt, cdn); + calculate_time_and_amount(frm); }, billing_rate: function(frm, cdt, cdn) { calculate_billing_costing_amount(frm, cdt, cdn); + calculate_time_and_amount(frm); }, costing_rate: function(frm, cdt, cdn) { calculate_billing_costing_amount(frm, cdt, cdn); + calculate_time_and_amount(frm); }, is_billable: function(frm, cdt, cdn) { update_billing_hours(frm, cdt, cdn); update_time_rates(frm, cdt, cdn); calculate_billing_costing_amount(frm, cdt, cdn); + calculate_time_and_amount(frm); }, activity_type: function(frm, cdt, cdn) { @@ -240,7 +282,8 @@ frappe.ui.form.on("Timesheet Detail", { method: "erpnext.projects.doctype.timesheet.timesheet.get_activity_cost", args: { employee: frm.doc.employee, - activity_type: frm.selected_doc.activity_type + activity_type: frm.selected_doc.activity_type, + currency: frm.doc.currency }, callback: function(r){ if(r.message){ @@ -290,17 +333,21 @@ var update_time_rates = function(frm, cdt, cdn) { }; var calculate_billing_costing_amount = function(frm, cdt, cdn) { - let child = frappe.get_doc(cdt, cdn); + let row = frappe.get_doc(cdt, cdn); let billing_amount = 0.0; - let costing_amount = 0.0; - - if (child.billing_hours && child.is_billable) { - billing_amount = (child.billing_hours * child.billing_rate); + let base_billing_amount = 0.0; + let exchange_rate = flt(frm.doc.exchange_rate); + frappe.model.set_value(cdt, cdn, 'base_billing_rate', flt(row.billing_rate) * exchange_rate); + frappe.model.set_value(cdt, cdn, 'base_costing_rate', flt(row.costing_rate) * exchange_rate); + if (row.billing_hours && row.is_billable) { + base_billing_amount = flt(row.billing_hours) * flt(row.base_billing_rate); + billing_amount = flt(row.billing_hours) * flt(row.billing_rate); } - costing_amount = flt(child.costing_rate * child.hours); + + frappe.model.set_value(cdt, cdn, 'base_billing_amount', base_billing_amount); + frappe.model.set_value(cdt, cdn, 'base_costing_amount', flt(row.base_costing_rate) * flt(row.hours)); 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); + frappe.model.set_value(cdt, cdn, 'costing_amount', flt(row.costing_rate) * flt(row.hours)); }; var calculate_time_and_amount = function(frm) { diff --git a/erpnext/projects/doctype/timesheet/timesheet.py b/erpnext/projects/doctype/timesheet/timesheet.py index d864c752794..1ee59aef8b8 100644 --- a/erpnext/projects/doctype/timesheet/timesheet.py +++ b/erpnext/projects/doctype/timesheet/timesheet.py @@ -14,6 +14,7 @@ from frappe.model.document import Document from erpnext.manufacturing.doctype.workstation.workstation import (check_if_within_operating_hours, WorkstationHolidayError) from erpnext.manufacturing.doctype.manufacturing_settings.manufacturing_settings import get_mins_between_operations +from erpnext.setup.utils import get_exchange_rate class OverlapError(frappe.ValidationError): pass class OverWorkLoggedError(frappe.ValidationError): pass @@ -37,9 +38,9 @@ class Timesheet(Document): self.total_hours = 0.0 self.total_billable_hours = 0.0 self.total_billed_hours = 0.0 - self.total_billable_amount = 0.0 - self.total_costing_amount = 0.0 - self.total_billed_amount = 0.0 + self.total_billable_amount = self.base_total_billable_amount = 0.0 + self.total_costing_amount = self.base_total_costing_amount = 0.0 + self.total_billed_amount = self.base_total_billed_amount = 0.0 for d in self.get("time_logs"): self.update_billing_hours(d) @@ -47,10 +48,13 @@ class Timesheet(Document): self.total_hours += flt(d.hours) self.total_costing_amount += flt(d.costing_amount) + self.base_total_costing_amount += flt(d.base_costing_amount) if d.is_billable: self.total_billable_hours += flt(d.billing_hours) self.total_billable_amount += flt(d.billing_amount) + self.base_total_billable_amount += flt(d.base_billing_amount) self.total_billed_amount += flt(d.billing_amount) if d.sales_invoice else 0.0 + self.base_total_billed_amount += flt(d.base_billing_amount) if d.sales_invoice else 0.0 self.total_billed_hours += flt(d.billing_hours) if d.sales_invoice else 0.0 def calculate_percentage_billed(self): @@ -330,12 +334,17 @@ def set_missing_values(time_sheet, target): }) @frappe.whitelist() -def get_activity_cost(employee=None, activity_type=None): +def get_activity_cost(employee=None, activity_type=None, currency=None): + base_currency = frappe.defaults.get_global_default('currency') rate = frappe.db.get_values("Activity Cost", {"employee": employee, "activity_type": activity_type}, ["costing_rate", "billing_rate"], as_dict=True) if not rate: rate = frappe.db.get_values("Activity Type", {"activity_type": activity_type}, ["costing_rate", "billing_rate"], as_dict=True) + if rate and currency and currency!=base_currency: + exchnage_rate = get_exchange_rate(base_currency, currency) + rate[0]["costing_rate"] = rate[0]["costing_rate"] * exchnage_rate + rate[0]["billing_rate"] = rate[0]["billing_rate"] * exchnage_rate return rate[0] if rate else {} diff --git a/erpnext/projects/doctype/timesheet_detail/timesheet_detail.json b/erpnext/projects/doctype/timesheet_detail/timesheet_detail.json index 0c9ed0bf202..ee04c612c9a 100644 --- a/erpnext/projects/doctype/timesheet_detail/timesheet_detail.json +++ b/erpnext/projects/doctype/timesheet_detail/timesheet_detail.json @@ -31,9 +31,13 @@ "column_break_8", "billing_hours", "section_break_11", + "base_billing_rate", + "base_billing_amount", + "base_costing_rate", + "base_costing_amount", + "column_break_14", "billing_rate", "billing_amount", - "column_break_14", "costing_rate", "costing_amount" ], @@ -230,12 +234,40 @@ "fieldname": "description", "fieldtype": "Small Text", "label": "Description" + }, + { + "fieldname": "base_billing_rate", + "fieldtype": "Currency", + "label": "Billing Rate", + "print_hide": 1, + "read_only": 1 + }, + { + "fieldname": "base_billing_amount", + "fieldtype": "Currency", + "label": "Billing Amount", + "print_hide": 1, + "read_only": 1 + }, + { + "fieldname": "base_costing_rate", + "fieldtype": "Currency", + "label": "Costing Rate", + "print_hide": 1, + "read_only": 1 + }, + { + "fieldname": "base_costing_amount", + "fieldtype": "Currency", + "label": "Costing Amount", + "print_hide": 1, + "read_only": 1 } ], "idx": 1, "istable": 1, "links": [], - "modified": "2021-05-15 16:16:10.688694", + "modified": "2021-05-18 12:19:33.205940", "modified_by": "Administrator", "module": "Projects", "name": "Timesheet Detail", From 5456873641be6ef354eefe01c7e37dd36962a336 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Sun, 16 May 2021 16:48:44 +0530 Subject: [PATCH 042/135] fix: run scheduler for reposting if there is no scheduler is running for the reposting --- .../repost_item_valuation/repost_item_valuation.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py index 27b8729ea05..5b626ea3458 100644 --- a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py +++ b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py @@ -4,8 +4,9 @@ from __future__ import unicode_literals import frappe, erpnext +from rq.timeouts import JobTimeoutException from frappe.model.document import Document -from frappe.utils import cint, get_link_to_form, add_to_date, now, today +from frappe.utils import cint, get_link_to_form, add_to_date, now, today, time_diff_in_hours from erpnext.stock.stock_ledger import repost_future_sle from erpnext.accounts.utils import update_gl_entries_after, check_if_stock_and_account_balance_synced from frappe.utils.user import get_users_with_role @@ -57,7 +58,8 @@ def repost(doc): repost_gl_entries(doc) doc.set_status('Completed') - except Exception: + + except (Exception, JobTimeoutException): frappe.db.rollback() traceback = frappe.get_traceback() frappe.log_error(traceback) @@ -113,6 +115,12 @@ def notify_error_to_stock_managers(doc, traceback): frappe.sendmail(recipients=recipients, subject=subject, message=message) def repost_entries(): + job_log = frappe.get_all('Scheduled Job Log', fields = ['status', 'creation'], + filters = {'scheduled_job_type': 'repost_item_valuation.repost_entries'}, order_by='creation desc', limit=1) + + if job_log and job_log[0]['status'] == 'Start' and time_diff_in_hours(now(), job_log[0]['creation']) < 2: + return + riv_entries = get_repost_item_valuation_entries() for row in riv_entries: From f79ef5d8cf91d9c4a3d7d390e024c47cb1ec963c Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Wed, 19 May 2021 13:04:44 +0530 Subject: [PATCH 043/135] fix: missing cost center message on creating gl entries --- erpnext/accounts/doctype/gl_entry/gl_entry.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.py b/erpnext/accounts/doctype/gl_entry/gl_entry.py index 78febf9c2ee..948c51364ed 100644 --- a/erpnext/accounts/doctype/gl_entry/gl_entry.py +++ b/erpnext/accounts/doctype/gl_entry/gl_entry.py @@ -75,8 +75,13 @@ class GLEntry(Document): def pl_must_have_cost_center(self): if frappe.get_cached_value("Account", self.account, "report_type") == "Profit and Loss": if not self.cost_center and self.voucher_type != 'Period Closing Voucher': - frappe.throw(_("{0} {1}: Cost Center is required for 'Profit and Loss' account {2}. Please set up a default Cost Center for the Company.") - .format(self.voucher_type, self.voucher_no, self.account)) + msg = _("{0} {1}: Cost Center is required for 'Profit and Loss' account {2}.").format( + self.voucher_type, self.voucher_no, self.account) + msg += " " + msg += _("Please set the cost center field in {0} or setup a default Cost Center for the Company.").format( + self.voucher_type) + + frappe.throw(msg, title=_("Missing Cost Center")) def validate_dimensions_for_pl_and_bs(self): account_type = frappe.db.get_value("Account", self.account, "report_type") From 3768216dca811aea0bddcffcf08ef8199c42747d Mon Sep 17 00:00:00 2001 From: noahjacob Date: Wed, 19 May 2021 13:50:35 +0530 Subject: [PATCH 044/135] refactor: updated permissions and mandatory fields --- .../supplier_item_group.json | 32 +++++++++++++++++-- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/erpnext/buying/doctype/supplier_item_group/supplier_item_group.json b/erpnext/buying/doctype/supplier_item_group/supplier_item_group.json index 1417ec23cf3..1971458f61e 100644 --- a/erpnext/buying/doctype/supplier_item_group/supplier_item_group.json +++ b/erpnext/buying/doctype/supplier_item_group/supplier_item_group.json @@ -14,19 +14,21 @@ "fieldtype": "Link", "in_list_view": 1, "label": "Supplier", - "options": "Supplier" + "options": "Supplier", + "reqd": 1 }, { "fieldname": "item_group", "fieldtype": "Link", "in_list_view": 1, "label": "Item Group", - "options": "Item Group" + "options": "Item Group", + "reqd": 1 } ], "index_web_pages_for_search": 1, "links": [], - "modified": "2021-05-07 18:16:40.621421", + "modified": "2021-05-19 13:48:16.742303", "modified_by": "Administrator", "module": "Buying", "name": "Supplier Item Group", @@ -43,6 +45,30 @@ "role": "System Manager", "share": 1, "write": 1 + }, + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Purchase User", + "share": 1, + "write": 1 + }, + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Purchase Manager", + "share": 1, + "write": 1 } ], "sort_field": "modified", From 8e34c49ac9130a7b523c83cb8cc0c005421e545c Mon Sep 17 00:00:00 2001 From: noahjacob Date: Wed, 19 May 2021 13:51:36 +0530 Subject: [PATCH 045/135] refactor: using get_all instead of get_list --- erpnext/controllers/queries.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py index e71b056c6e2..f5668c51fea 100644 --- a/erpnext/controllers/queries.py +++ b/erpnext/controllers/queries.py @@ -217,7 +217,7 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals searchfields = " or ".join([field + " like %(txt)s" for field in searchfields]) if filters.get('supplier'): - item_group_list = frappe.get_list('Supplier Item Group', filters = {'supplier': filters.get('supplier')}, fields = ['item_group']) + item_group_list = frappe.get_all('Supplier Item Group', filters = {'supplier': filters.get('supplier')}, fields = ['item_group']) item_groups = [] for i in item_group_list: From bf7f0530e6cc14cb7722c767259c0c814fb1a8b8 Mon Sep 17 00:00:00 2001 From: noahjacob Date: Wed, 19 May 2021 13:53:22 +0530 Subject: [PATCH 046/135] fix: added error handling if entry already exists --- .../supplier_item_group/supplier_item_group.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/erpnext/buying/doctype/supplier_item_group/supplier_item_group.py b/erpnext/buying/doctype/supplier_item_group/supplier_item_group.py index 6fbeb372429..3a2e5d6dcef 100644 --- a/erpnext/buying/doctype/supplier_item_group/supplier_item_group.py +++ b/erpnext/buying/doctype/supplier_item_group/supplier_item_group.py @@ -3,8 +3,16 @@ # For license information, please see license.txt from __future__ import unicode_literals -# import frappe +import frappe +from frappe import _ from frappe.model.document import Document class SupplierItemGroup(Document): - pass + def validate(self): + exists = frappe.db.exists({ + 'doctype': 'Supplier Item Group', + 'supplier': self.supplier, + 'item_group': self.item_group + }) + if exists: + frappe.throw(_("Item Group has already been linked to this supplier.")) \ No newline at end of file From 4e73c8a79f1838de0f0d828da71aaad5110b4e3c Mon Sep 17 00:00:00 2001 From: Anupam Date: Wed, 19 May 2021 14:58:12 +0530 Subject: [PATCH 047/135] restructuring timesheet fields --- .../projects/doctype/timesheet/timesheet.js | 20 +++++++---- .../projects/doctype/timesheet/timesheet.json | 36 +++++++++++++++++-- 2 files changed, 46 insertions(+), 10 deletions(-) diff --git a/erpnext/projects/doctype/timesheet/timesheet.js b/erpnext/projects/doctype/timesheet/timesheet.js index 532d64994f1..4512244027d 100644 --- a/erpnext/projects/doctype/timesheet/timesheet.js +++ b/erpnext/projects/doctype/timesheet/timesheet.js @@ -145,14 +145,20 @@ frappe.ui.form.on("Timesheet", { let base_currency = frappe.defaults.get_global_default('currency'); frm.set_currency_labels(["base_total_costing_amount", "base_total_billable_amount", "base_total_billed_amount"], base_currency); frm.set_currency_labels(["total_costing_amount", "total_billable_amount", "total_billed_amount"], frm.doc.currency); - frm.set_currency_labels(["base_billing_rate", "base_billing_amount", "base_costing_rate", "base_costing_amount"], base_currency, "time_logs"); - frm.set_currency_labels(["billing_rate", "billing_amount", "costing_rate", "costing_amount"], frm.doc.currency, "time_logs"); - let time_logs_grid = frm.fields_dict.time_logs.grid; - $.each(["base_billing_rate", "base_billing_amount", "base_costing_rate", "base_costing_amount"], function(i, d) { - if(frappe.meta.get_docfield(time_logs_grid.doctype, d)) - time_logs_grid.set_column_disp(d, frm.doc.currency != base_currency); - }); + frm.toggle_display(["base_total_costing_amount", "base_total_billable_amount", "base_total_billed_amount"], + frm.doc.currency != base_currency) + + if (frm.doc?.time_logs.length > 0) { + frm.set_currency_labels(["base_billing_rate", "base_billing_amount", "base_costing_rate", "base_costing_amount"], base_currency, "time_logs"); + frm.set_currency_labels(["billing_rate", "billing_amount", "costing_rate", "costing_amount"], frm.doc.currency, "time_logs"); + + let time_logs_grid = frm.fields_dict.time_logs.grid; + $.each(["base_billing_rate", "base_billing_amount", "base_costing_rate", "base_costing_amount"], function(i, d) { + if (frappe.meta.get_docfield(time_logs_grid.doctype, d)) + time_logs_grid.set_column_disp(d, frm.doc.currency != base_currency); + }); + } frm.refresh_fields(); }, diff --git a/erpnext/projects/doctype/timesheet/timesheet.json b/erpnext/projects/doctype/timesheet/timesheet.json index 23e6ede967b..75f7478ed18 100644 --- a/erpnext/projects/doctype/timesheet/timesheet.json +++ b/erpnext/projects/doctype/timesheet/timesheet.json @@ -13,6 +13,7 @@ "company", "customer", "currency", + "exchange_rate", "sales_invoice", "column_break_3", "salary_slip", @@ -32,11 +33,14 @@ "total_hours", "billing_details", "total_billable_hours", - "total_billed_hours", - "total_costing_amount", + "base_total_billable_amount", + "base_total_billed_amount", + "base_total_costing_amount", "column_break_10", + "total_billed_hours", "total_billable_amount", "total_billed_amount", + "total_costing_amount", "per_billed", "section_break_18", "note", @@ -283,13 +287,39 @@ "fieldtype": "Link", "label": "Currency", "options": "Currency" + }, + { + "fieldname": "base_total_costing_amount", + "fieldtype": "Currency", + "label": "Total Costing Amount", + "print_hide": 1, + "read_only": 1 + }, + { + "fieldname": "base_total_billable_amount", + "fieldtype": "Currency", + "label": "Total Billable Amount", + "print_hide": 1, + "read_only": 1 + }, + { + "fieldname": "base_total_billed_amount", + "fieldtype": "Currency", + "label": "Total Billed Amount", + "print_hide": 1, + "read_only": 1 + }, + { + "fieldname": "exchange_rate", + "fieldtype": "Float", + "label": "Exchange Rate" } ], "icon": "fa fa-clock-o", "idx": 1, "is_submittable": 1, "links": [], - "modified": "2021-05-13 17:13:29.954960", + "modified": "2021-05-18 16:10:08.249619", "modified_by": "Administrator", "module": "Projects", "name": "Timesheet", From 4bd641367b24a49fd8c4e2e896a960455c560f00 Mon Sep 17 00:00:00 2001 From: Saqib Date: Wed, 19 May 2021 16:38:53 +0530 Subject: [PATCH 048/135] fix: address template with upper filter throws jinja error (#25756) --- erpnext/regional/address_template/templates/united_states.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/regional/address_template/templates/united_states.html b/erpnext/regional/address_template/templates/united_states.html index 089315e4e4c..77fce46b9d7 100644 --- a/erpnext/regional/address_template/templates/united_states.html +++ b/erpnext/regional/address_template/templates/united_states.html @@ -1,4 +1,4 @@ {{ address_line1 }}
{% if address_line2 %}{{ address_line2 }}
{% endif -%} {{ city }}, {% if state %}{{ state }}{% endif -%}{% if pincode %} {{ pincode }}
{% endif -%} -{% if country != "United States" %}{{ country|upper }}{% endif -%} +{% if country != "United States" %}{{ country }}{% endif -%} From 7fb385a89f12f4ed22d01282020793686c415ce2 Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Wed, 19 May 2021 18:47:06 +0530 Subject: [PATCH 049/135] fix: cannot bypass e-invoicing for non gst item invoices --- erpnext/regional/india/e_invoice/utils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/regional/india/e_invoice/utils.py b/erpnext/regional/india/e_invoice/utils.py index b4e7a8889ef..0315c83fd15 100644 --- a/erpnext/regional/india/e_invoice/utils.py +++ b/erpnext/regional/india/e_invoice/utils.py @@ -43,8 +43,9 @@ def validate_eligibility(doc): invalid_supply_type = doc.get('gst_category') not in ['Registered Regular', 'SEZ', 'Overseas', 'Deemed Export'] company_transaction = doc.get('billing_address_gstin') == doc.get('company_gstin') no_taxes_applied = not doc.get('taxes') + has_non_gst_item = any(d for d in doc.get('items') if frappe.db.get_value('Item', d.get('item_code'), 'is_non_gst')) - if invalid_company or invalid_supply_type or company_transaction or no_taxes_applied: + if invalid_company or invalid_supply_type or company_transaction or no_taxes_applied or has_non_gst_item: return False return True From b9ad385232d5e6a66fa418bdb879b3eb85c263b3 Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Wed, 19 May 2021 19:13:06 +0530 Subject: [PATCH 050/135] fix: remove uncessary query --- erpnext/regional/india/e_invoice/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/regional/india/e_invoice/utils.py b/erpnext/regional/india/e_invoice/utils.py index 0315c83fd15..70e6d07eab1 100644 --- a/erpnext/regional/india/e_invoice/utils.py +++ b/erpnext/regional/india/e_invoice/utils.py @@ -43,7 +43,7 @@ def validate_eligibility(doc): invalid_supply_type = doc.get('gst_category') not in ['Registered Regular', 'SEZ', 'Overseas', 'Deemed Export'] company_transaction = doc.get('billing_address_gstin') == doc.get('company_gstin') no_taxes_applied = not doc.get('taxes') - has_non_gst_item = any(d for d in doc.get('items') if frappe.db.get_value('Item', d.get('item_code'), 'is_non_gst')) + has_non_gst_item = any(d for d in doc.get('items') if d.get('is_non_gst')) if invalid_company or invalid_supply_type or company_transaction or no_taxes_applied or has_non_gst_item: return False From aeb88385bbae9470956aefec57d69eb3a6fbc0fa Mon Sep 17 00:00:00 2001 From: Anupam Date: Thu, 20 May 2021 14:11:36 +0530 Subject: [PATCH 051/135] patch: timesheet changes --- erpnext/patches.txt | 2 +- ...me_billable_to_is_billable_in_timesheet.py | 7 ------ .../patches/v13_0/update_timesheet_changes.py | 24 +++++++++++++++++++ 3 files changed, 25 insertions(+), 8 deletions(-) delete mode 100644 erpnext/patches/v13_0/rename_billable_to_is_billable_in_timesheet.py create mode 100644 erpnext/patches/v13_0/update_timesheet_changes.py diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 0caad586e5a..d4655e19b91 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -779,4 +779,4 @@ erpnext.patches.v12_0.add_ewaybill_validity_field erpnext.patches.v13_0.germany_make_custom_fields erpnext.patches.v13_0.germany_fill_debtor_creditor_number erpnext.patches.v13_0.set_pos_closing_as_failed -erpnext.patches.v13_0.rename_billable_to_is_billable_in_timesheet +erpnext.patches.v13_0.update_timesheet_changes diff --git a/erpnext/patches/v13_0/rename_billable_to_is_billable_in_timesheet.py b/erpnext/patches/v13_0/rename_billable_to_is_billable_in_timesheet.py deleted file mode 100644 index 6860a37559e..00000000000 --- a/erpnext/patches/v13_0/rename_billable_to_is_billable_in_timesheet.py +++ /dev/null @@ -1,7 +0,0 @@ -from __future__ import unicode_literals -import frappe -from frappe.model.utils.rename_field import rename_field - -def execute(): - if "billable" in frappe.db.get_table_columns("Timesheet Detail"): - rename_field("Timesheet Detail", "billable", "is_billable") \ No newline at end of file diff --git a/erpnext/patches/v13_0/update_timesheet_changes.py b/erpnext/patches/v13_0/update_timesheet_changes.py new file mode 100644 index 00000000000..87178b2f842 --- /dev/null +++ b/erpnext/patches/v13_0/update_timesheet_changes.py @@ -0,0 +1,24 @@ +from __future__ import unicode_literals +import frappe +from frappe.model.utils.rename_field import rename_field + +def execute(): + if "billable" in frappe.db.get_table_columns("Timesheet Detail"): + rename_field("Timesheet Detail", "billable", "is_billable") + + base_currency = frappe.defaults.get_global_default('currency') + frappe.reload_doc("projects", "doctype", "timesheet") + frappe.reload_doc("projects", "doctype", "timesheet_detail") + + frappe.db.sql("""UPDATE `tabTimesheet Detail` + SET base_billing_rate = billing_rate, + base_billing_amount = billing_amount, + base_costing_rate = costing_rate, + base_costing_amount = costing_amount""") + + frappe.db.sql("""UPDATE `tabTimesheet` + SET currency = '{0}', + exchange_rate = 1.0, + base_total_billable_amount = total_billable_amount, + base_total_billed_amount = total_billed_amount, + base_total_costing_amount = total_costing_amount""".format(base_currency)) \ No newline at end of file From aa516e5d178769a07fe1c400f60e96ca54ac36a7 Mon Sep 17 00:00:00 2001 From: Anupam Date: Thu, 20 May 2021 14:12:18 +0530 Subject: [PATCH 052/135] fix: review changes --- erpnext/projects/doctype/timesheet/timesheet.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/projects/doctype/timesheet/timesheet.js b/erpnext/projects/doctype/timesheet/timesheet.js index 4512244027d..9bb9c385324 100644 --- a/erpnext/projects/doctype/timesheet/timesheet.js +++ b/erpnext/projects/doctype/timesheet/timesheet.js @@ -116,7 +116,7 @@ frappe.ui.form.on("Timesheet", { currency: function(frm) { let base_currency = frappe.defaults.get_global_default('currency'); - if (base_currency != frm.doc.company) { + if (base_currency != frm.doc.currency) { frappe.call({ method: "erpnext.setup.utils.get_exchange_rate", args: { From 1270febfffc16fc6c548487727629b56f57fa354 Mon Sep 17 00:00:00 2001 From: Anupam Date: Thu, 20 May 2021 14:15:58 +0530 Subject: [PATCH 053/135] fix: sider issues --- erpnext/patches/v13_0/update_timesheet_changes.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/patches/v13_0/update_timesheet_changes.py b/erpnext/patches/v13_0/update_timesheet_changes.py index 87178b2f842..3acce18c638 100644 --- a/erpnext/patches/v13_0/update_timesheet_changes.py +++ b/erpnext/patches/v13_0/update_timesheet_changes.py @@ -11,13 +11,13 @@ def execute(): frappe.reload_doc("projects", "doctype", "timesheet_detail") frappe.db.sql("""UPDATE `tabTimesheet Detail` - SET base_billing_rate = billing_rate, + SET base_billing_rate = billing_rate, base_billing_amount = billing_amount, base_costing_rate = costing_rate, base_costing_amount = costing_amount""") frappe.db.sql("""UPDATE `tabTimesheet` - SET currency = '{0}', + SET currency = '{0}', exchange_rate = 1.0, base_total_billable_amount = total_billable_amount, base_total_billed_amount = total_billed_amount, From 4427390ab386c54b7de9e78d551bfa8ed1d6c502 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Thu, 20 May 2021 17:19:24 +0530 Subject: [PATCH 054/135] fix: Do not throw error in migrate --- erpnext/regional/india/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py index ca679e43d2e..fc227defbfc 100644 --- a/erpnext/regional/india/utils.py +++ b/erpnext/regional/india/utils.py @@ -695,7 +695,7 @@ def get_gst_accounts(company=None, account_wise=False, only_reverse_charge=0, on filters=filters, fields=["cgst_account", "sgst_account", "igst_account", "cess_account"]) - if not gst_settings_accounts and not frappe.flags.in_test: + if not gst_settings_accounts and not frappe.flags.in_test and not frappe.flags.in_migrate: frappe.throw(_("Please set GST Accounts in GST Settings")) for d in gst_settings_accounts: From 21e662f67870ed37a887c5ffbffb18622d84bb6c Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Mohsin Rajan Date: Thu, 20 May 2021 17:20:05 +0530 Subject: [PATCH 055/135] fix: apply permission while selecting projects (#25765) --- erpnext/projects/doctype/task/task.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/erpnext/projects/doctype/task/task.js b/erpnext/projects/doctype/task/task.js index 6a9d2d1424a..3cd92ee719d 100644 --- a/erpnext/projects/doctype/task/task.js +++ b/erpnext/projects/doctype/task/task.js @@ -5,12 +5,6 @@ frappe.provide("erpnext.projects"); frappe.ui.form.on("Task", { setup: function (frm) { - frm.set_query("project", function () { - return { - query: "erpnext.projects.doctype.task.task.get_project" - } - }); - frm.make_methods = { 'Timesheet': () => frappe.model.open_mapped_doc({ method: 'erpnext.projects.doctype.task.task.make_timesheet', From 0d8b9a9d0a110d7379ebb9eba9e96d61bb1ca02b Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Thu, 20 May 2021 19:53:30 +0530 Subject: [PATCH 056/135] fix(patch): billable field not renamed --- erpnext/patches/v13_0/update_timesheet_changes.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/erpnext/patches/v13_0/update_timesheet_changes.py b/erpnext/patches/v13_0/update_timesheet_changes.py index 3acce18c638..93b7f8e59a4 100644 --- a/erpnext/patches/v13_0/update_timesheet_changes.py +++ b/erpnext/patches/v13_0/update_timesheet_changes.py @@ -3,19 +3,20 @@ import frappe from frappe.model.utils.rename_field import rename_field def execute(): - if "billable" in frappe.db.get_table_columns("Timesheet Detail"): - rename_field("Timesheet Detail", "billable", "is_billable") - - base_currency = frappe.defaults.get_global_default('currency') frappe.reload_doc("projects", "doctype", "timesheet") frappe.reload_doc("projects", "doctype", "timesheet_detail") + if frappe.db.has_column("Timesheet Detail", "billable"): + rename_field("Timesheet Detail", "billable", "is_billable") + + base_currency = frappe.defaults.get_global_default('currency') + frappe.db.sql("""UPDATE `tabTimesheet Detail` SET base_billing_rate = billing_rate, base_billing_amount = billing_amount, base_costing_rate = costing_rate, base_costing_amount = costing_amount""") - + frappe.db.sql("""UPDATE `tabTimesheet` SET currency = '{0}', exchange_rate = 1.0, From be247ec3ded28cec31228a61f9ea8e8ceb29cc88 Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Thu, 20 May 2021 22:17:20 +0530 Subject: [PATCH 057/135] fix: error message placeholders and sider issues --- erpnext/projects/doctype/timesheet/timesheet.js | 4 ++-- erpnext/projects/doctype/timesheet/timesheet.py | 16 ++++++++-------- erpnext/public/js/utils.js | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/erpnext/projects/doctype/timesheet/timesheet.js b/erpnext/projects/doctype/timesheet/timesheet.js index 9bb9c385324..63078ea7bd2 100644 --- a/erpnext/projects/doctype/timesheet/timesheet.js +++ b/erpnext/projects/doctype/timesheet/timesheet.js @@ -146,10 +146,10 @@ frappe.ui.form.on("Timesheet", { frm.set_currency_labels(["base_total_costing_amount", "base_total_billable_amount", "base_total_billed_amount"], base_currency); frm.set_currency_labels(["total_costing_amount", "total_billable_amount", "total_billed_amount"], frm.doc.currency); - frm.toggle_display(["base_total_costing_amount", "base_total_billable_amount", "base_total_billed_amount"], + frm.toggle_display(["base_total_costing_amount", "base_total_billable_amount", "base_total_billed_amount"], frm.doc.currency != base_currency) - if (frm.doc?.time_logs.length > 0) { + if (frm.doc.time_logs.length > 0) { frm.set_currency_labels(["base_billing_rate", "base_billing_amount", "base_costing_rate", "base_costing_amount"], base_currency, "time_logs"); frm.set_currency_labels(["billing_rate", "billing_amount", "costing_rate", "costing_amount"], frm.doc.currency, "time_logs"); diff --git a/erpnext/projects/doctype/timesheet/timesheet.py b/erpnext/projects/doctype/timesheet/timesheet.py index 1ee59aef8b8..d3c21a3728d 100644 --- a/erpnext/projects/doctype/timesheet/timesheet.py +++ b/erpnext/projects/doctype/timesheet/timesheet.py @@ -150,7 +150,7 @@ class Timesheet(Document): def validate_project(self, data): if self.parent_project and self.parent_project != data.project: - frappe.throw(_("Row {0}: Project must be same as the one set in the Timesheet: {1}.")).format(data.idx, self.parent_project) + frappe.throw(_("Row {0}: Project must be same as the one set in the Timesheet: {1}.").format(data.idx, self.parent_project)) def validate_overlap_for(self, fieldname, args, value, ignore_validation=False): if not value or ignore_validation: @@ -221,14 +221,14 @@ def get_projectwise_timesheet_data(project=None, parent=None, from_time=None, to if from_time and to_time: condition += "AND CAST(tsd.from_time as DATE) BETWEEN %(from_time)s AND %(to_time)s" - return frappe.db.sql("""SELECT tsd.name as name, - tsd.parent as parent, tsd.billing_hours as billing_hours, - tsd.billing_amount as billing_amount, tsd.activity_type as activity_type, + return frappe.db.sql("""SELECT tsd.name as name, + tsd.parent as parent, tsd.billing_hours as billing_hours, + tsd.billing_amount as billing_amount, tsd.activity_type as activity_type, tsd.description as description, ts.currency as currency - FROM `tabTimesheet Detail` tsd - INNER JOIN `tabTimesheet` ts ON ts.name = tsd.parent - WHERE tsd.parenttype = 'Timesheet' - and tsd.docstatus=1 {0} + FROM `tabTimesheet Detail` tsd + INNER JOIN `tabTimesheet` ts ON ts.name = tsd.parent + WHERE tsd.parenttype = 'Timesheet' + and tsd.docstatus=1 {0} and tsd.is_billable = 1 and tsd.sales_invoice is null""".format(condition), {'project': project, 'parent': parent, 'from_time': from_time, 'to_time': to_time}, as_dict=1) diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js index 39004503a0c..ce40ced11f2 100755 --- a/erpnext/public/js/utils.js +++ b/erpnext/public/js/utils.js @@ -734,7 +734,7 @@ frappe.form.link_formatters['Project'] = function(value, doc) { // if value is blank in report view or project name and name are the same, return as is return value; } -} +}; // add description on posting time $(document).on('app_ready', function() { From 8a407f1ec308ef4a4c142746cebf39e18c72ed53 Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Thu, 20 May 2021 22:23:44 +0530 Subject: [PATCH 058/135] fix: sider issues --- erpnext/projects/doctype/timesheet/timesheet.js | 2 +- erpnext/projects/doctype/timesheet/timesheet.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/projects/doctype/timesheet/timesheet.js b/erpnext/projects/doctype/timesheet/timesheet.js index 63078ea7bd2..84c7b8118b8 100644 --- a/erpnext/projects/doctype/timesheet/timesheet.js +++ b/erpnext/projects/doctype/timesheet/timesheet.js @@ -147,7 +147,7 @@ frappe.ui.form.on("Timesheet", { frm.set_currency_labels(["total_costing_amount", "total_billable_amount", "total_billed_amount"], frm.doc.currency); frm.toggle_display(["base_total_costing_amount", "base_total_billable_amount", "base_total_billed_amount"], - frm.doc.currency != base_currency) + frm.doc.currency != base_currency); if (frm.doc.time_logs.length > 0) { frm.set_currency_labels(["base_billing_rate", "base_billing_amount", "base_costing_rate", "base_costing_amount"], base_currency, "time_logs"); diff --git a/erpnext/projects/doctype/timesheet/timesheet.py b/erpnext/projects/doctype/timesheet/timesheet.py index d3c21a3728d..d42c6ab1758 100644 --- a/erpnext/projects/doctype/timesheet/timesheet.py +++ b/erpnext/projects/doctype/timesheet/timesheet.py @@ -137,7 +137,7 @@ class Timesheet(Document): def validate_time_logs(self): for data in self.get('time_logs'): self.validate_overlap(data) - self.validate_task_project(data) + self.set_project(data) self.validate_project(data) def validate_overlap(self, data): @@ -145,7 +145,7 @@ class Timesheet(Document): self.validate_overlap_for("user", data, self.user, settings.ignore_user_time_overlap) self.validate_overlap_for("employee", data, self.employee, settings.ignore_employee_time_overlap) - def validate_task_project(self, data): + def set_project(self, data): data.project = data.project or frappe.db.get_value("Task", data.task, "project") def validate_project(self, data): From a7d0dbb085f23f3cedc1b88b546bcc64cb029d56 Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Thu, 20 May 2021 23:02:11 +0530 Subject: [PATCH 059/135] fix: calculate total billing amount on fetching timesheets - show timesheet billing amounts in doc currency --- .../doctype/sales_invoice/sales_invoice.js | 57 +++++++++---------- .../doctype/sales_invoice/sales_invoice.json | 5 +- .../sales_invoice_timesheet.json | 3 +- .../projects/doctype/timesheet/timesheet.py | 6 +- 4 files changed, 35 insertions(+), 36 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js index 747d0a931a5..1808005f62d 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js @@ -820,7 +820,7 @@ frappe.ui.form.on('Sales Invoice', { }, add_timesheet_row: function(frm, row, exchange_rate) { - frm.add_child('timesheets',{ + frm.add_child('timesheets', { 'activity_type': row.activity_type, 'description': row.description, 'time_sheet': row.parent, @@ -828,7 +828,8 @@ frappe.ui.form.on('Sales Invoice', { 'billing_amount': flt(row.billing_amount) * flt(exchange_rate), 'timesheet_detail': row.name }); - frm.refresh_field('timesheets') + frm.refresh_field('timesheets'); + calculate_total_billing_amount(frm); }, refresh: function(frm) { @@ -871,36 +872,32 @@ frappe.ui.form.on('Sales Invoice', { project: data.project }, callback: function(r) { - if(!r.exc) { - if(r.message.length > 0) { - frm.clear_table('timesheets') - r.message.forEach((d) => { - let exchange_rate = 1.0; - if (frm.doc.currency != d.currency) { - frappe.call({ - method: "erpnext.setup.utils.get_exchange_rate", - args: { - from_currency: d.currency, - to_currency: frm.doc.currency - }, - callback: function(r) { - if (r.message) { - exchange_rate = r.message; - frm.events.add_timesheet_row(frm, d, exchange_rate); - } + if (!r.exc && r.message.length > 0) { + frm.clear_table('timesheets') + r.message.forEach((d) => { + let exchange_rate = 1.0; + if (frm.doc.currency != d.currency) { + frappe.call({ + method: 'erpnext.setup.utils.get_exchange_rate', + args: { + from_currency: d.currency, + to_currency: frm.doc.currency + }, + callback: function(r) { + if (r.message) { + exchange_rate = r.message; + frm.events.add_timesheet_row(frm, d, exchange_rate); } - }); - } - else { - frm.events.add_timesheet_row(frm, d, exchange_rate); - } - }); - } - else { - frappe.msgprint(__('No Timesheet Found.')) - } - d.hide(); + } + }); + } else { + frm.events.add_timesheet_row(frm, d, exchange_rate); + } + }); + } else { + frappe.msgprint(__('No Timesheets found with the selected filters.')) } + d.hide(); } }); }, diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json index 48d644cb432..e7dd6b8a606 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json @@ -772,6 +772,7 @@ "hide_days": 1, "hide_seconds": 1, "label": "Total Billing Amount", + "options": "currency", "print_hide": 1, "read_only": 1 }, @@ -1960,7 +1961,7 @@ "label": "Is Debit Note" }, { - "default": 0, + "default": "0", "depends_on": "grand_total", "fieldname": "disable_rounded_total", "fieldtype": "Check", @@ -1977,7 +1978,7 @@ "link_fieldname": "consolidated_invoice" } ], - "modified": "2021-05-13 17:53:26.185370", + "modified": "2021-05-20 22:48:33.988881", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice", diff --git a/erpnext/accounts/doctype/sales_invoice_timesheet/sales_invoice_timesheet.json b/erpnext/accounts/doctype/sales_invoice_timesheet/sales_invoice_timesheet.json index 9321630829c..f069e8dd0b8 100644 --- a/erpnext/accounts/doctype/sales_invoice_timesheet/sales_invoice_timesheet.json +++ b/erpnext/accounts/doctype/sales_invoice_timesheet/sales_invoice_timesheet.json @@ -34,6 +34,7 @@ "fieldtype": "Currency", "in_list_view": 1, "label": "Billing Amount", + "options": "currency", "read_only": 1 }, { @@ -64,7 +65,7 @@ ], "istable": 1, "links": [], - "modified": "2021-05-13 16:52:32.995266", + "modified": "2021-05-20 22:33:57.234846", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice Timesheet", diff --git a/erpnext/projects/doctype/timesheet/timesheet.py b/erpnext/projects/doctype/timesheet/timesheet.py index d42c6ab1758..a3e4577f909 100644 --- a/erpnext/projects/doctype/timesheet/timesheet.py +++ b/erpnext/projects/doctype/timesheet/timesheet.py @@ -342,9 +342,9 @@ def get_activity_cost(employee=None, activity_type=None, currency=None): rate = frappe.db.get_values("Activity Type", {"activity_type": activity_type}, ["costing_rate", "billing_rate"], as_dict=True) if rate and currency and currency!=base_currency: - exchnage_rate = get_exchange_rate(base_currency, currency) - rate[0]["costing_rate"] = rate[0]["costing_rate"] * exchnage_rate - rate[0]["billing_rate"] = rate[0]["billing_rate"] * exchnage_rate + exchange_rate = get_exchange_rate(base_currency, currency) + rate[0]["costing_rate"] = rate[0]["costing_rate"] * exchange_rate + rate[0]["billing_rate"] = rate[0]["billing_rate"] * exchange_rate return rate[0] if rate else {} From 605ea044f37510cf8f12daf2a5f82a5ea44d3002 Mon Sep 17 00:00:00 2001 From: Anuja P Date: Fri, 21 May 2021 11:24:33 +0530 Subject: [PATCH 060/135] fix: update process SOA format --- .../process_statement_of_accounts.html | 118 ++++++++++-------- .../process_statement_of_accounts.json | 19 ++- .../process_statement_of_accounts.py | 8 +- 3 files changed, 92 insertions(+), 53 deletions(-) diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.html b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.html index f61aacbce27..7328f168e3d 100644 --- a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.html +++ b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.html @@ -1,24 +1,42 @@ -

{{ filters.party[0] }}

-

{{ _("Statement of Accounts") }}

+
+
+ {% if letter_head %} +
{{ letter_head.content }}
+
+ {% endif %} +
+ +

{{ _("STATEMENTS OF ACCOUNTS") }}

+
+
{{ _("Customer: ") }} {{filters.party[0] }}
+
+ {{ _("Date: ") }} + {{ frappe.format(filters.from_date, 'Date')}} + {{ _("to") }} + {{ frappe.format(filters.to_date, 'Date')}} +
+
+
-
- {{ frappe.format(filters.from_date, 'Date')}} - {{ _("to") }} - {{ frappe.format(filters.to_date, 'Date')}} -
- - - - - - - - - - - - - +
{{ _("Date") }}{{ _("Ref") }}{{ _("Party") }}{{ _("Debit") }}{{ _("Credit") }}{{ _("Balance (Dr - Cr)") }}
+ + + + + + + + + + + {% for row in data %} {% if(row.posting_date) %} @@ -58,32 +76,34 @@ {% endfor %} -
{{ _("Date") }}{{ _("Reference") }}{{ _("Remarks") }}{{ _("Debit") }}{{ _("Credit") }}{{ _("Balance (Dr - Cr)") }}
-

-{% if ageing %} -

{{ _("Ageing Report Based On ") }} {{ ageing.ageing_based_on }}

-
- {{ _("Up to " ) }} {{ frappe.format(filters.to_date, 'Date')}} -
-
- - - - - - - - - - - - - - - - - - -
30 Days60 Days90 Days120 Days
{{ frappe.utils.fmt_money(ageing.range1, currency=filters.presentation_currency) }}{{ frappe.utils.fmt_money(ageing.range2, currency=filters.presentation_currency) }}{{ frappe.utils.fmt_money(ageing.range3, currency=filters.presentation_currency) }}{{ frappe.utils.fmt_money(ageing.range4, currency=filters.presentation_currency) }}
-{% endif %} -

Printed On {{ frappe.format(frappe.utils.get_datetime(), 'Datetime') }}

\ No newline at end of file + +
+ {% if ageing %} +

{{ _("Ageing Report based on ") }} {{ ageing.ageing_based_on }} + {{ _("up to " ) }} {{ frappe.format(filters.to_date, 'Date')}} +

+ + + + + + + + + + + + + + + + + +
30 Days60 Days90 Days120 Days
{{ frappe.utils.fmt_money(ageing.range1, currency=filters.presentation_currency) }}{{ frappe.utils.fmt_money(ageing.range2, currency=filters.presentation_currency) }}{{ frappe.utils.fmt_money(ageing.range3, currency=filters.presentation_currency) }}{{ frappe.utils.fmt_money(ageing.range4, currency=filters.presentation_currency) }}
+ {% endif %} + {% if terms_and_conditions %} +
+ {{ terms_and_conditions }} +
+ {% endif %} +
\ No newline at end of file diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.json b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.json index 4be0e2ec068..27a5f50ce2a 100644 --- a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.json +++ b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.json @@ -1,6 +1,5 @@ { "actions": [], - "allow_workflow": 1, "autoname": "Prompt", "creation": "2020-05-22 16:46:18.712954", "doctype": "DocType", @@ -28,9 +27,11 @@ "customers", "preferences", "orientation", - "section_break_14", "include_ageing", "ageing_based_on", + "section_break_14", + "letter_head", + "terms_and_conditions", "section_break_1", "enable_auto_email", "section_break_18", @@ -270,10 +271,22 @@ "fieldname": "body", "fieldtype": "Text Editor", "label": "Body" + }, + { + "fieldname": "letter_head", + "fieldtype": "Link", + "label": "Letter Head", + "options": "Letter Head" + }, + { + "fieldname": "terms_and_conditions", + "fieldtype": "Link", + "label": "Terms and Conditions", + "options": "Terms and Conditions" } ], "links": [], - "modified": "2020-08-08 08:47:09.185728", + "modified": "2021-05-21 10:14:22.426672", "modified_by": "Administrator", "module": "Accounts", "name": "Process Statement Of Accounts", diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py index a0dbff3db43..2ad455c48ff 100644 --- a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py +++ b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py @@ -64,6 +64,9 @@ def get_report_pdf(doc, consolidated=True): tax_id = frappe.get_doc('Customer', entry.customer).tax_id presentation_currency = get_party_account_currency('Customer', entry.customer, doc.company) \ or doc.currency or get_company_currency(doc.company) + if doc.letter_head: + from frappe.www.printview import get_letter_head + letter_head = get_letter_head(doc, 0) filters= frappe._dict({ 'from_date': doc.from_date, @@ -91,7 +94,10 @@ def get_report_pdf(doc, consolidated=True): continue html = frappe.render_template(template_path, \ - {"filters": filters, "data": res, "ageing": ageing[0] if (doc.include_ageing and ageing) else None}) + {"filters": filters, "data": res, "ageing": ageing[0] if doc.include_ageing else None, + "letter_head": letter_head if doc.letter_head else None, + "terms_and_conditions": frappe.db.get_value('Terms and Conditions', doc.terms_and_conditions, 'terms') + if doc.terms_and_conditions else None}) html = frappe.render_template(base_template_path, {"body": html, \ "css": get_print_style(), "title": "Statement For " + entry.customer}) From 795909fdcd0b682c54129b7226a93b99f1240db1 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Fri, 21 May 2021 11:23:20 +0530 Subject: [PATCH 061/135] fix: warehouse not found in stock entry --- erpnext/stock/doctype/stock_entry/stock_entry.js | 4 ++-- erpnext/stock/doctype/stock_entry/stock_entry.json | 4 +++- .../doctype/stock_entry_type/stock_entry_type.json | 12 ++++++++++-- .../doctype/stock_entry_type/stock_entry_type.py | 4 +++- 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js index daa1e511820..a40ef001ee9 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.js +++ b/erpnext/stock/doctype/stock_entry/stock_entry.js @@ -600,7 +600,6 @@ frappe.ui.form.on('Stock Entry', { add_to_transit: function(frm) { if(frm.doc.add_to_transit && frm.doc.purpose=='Material Transfer') { frm.set_value('to_warehouse', ''); - frm.set_value('stock_entry_type', 'Material Transfer'); frm.fields_dict.to_warehouse.get_query = function() { return { filters:{ @@ -615,7 +614,8 @@ frappe.ui.form.on('Stock Entry', { }, set_tansit_warehouse: function(frm) { - if(frm.doc.add_to_transit && frm.doc.purpose == 'Material Transfer' && !frm.doc.to_warehouse) { + if(frm.doc.add_to_transit && frm.doc.purpose == 'Material Transfer' && !frm.doc.to_warehouse + && frm.doc.from_warehouse) { let dt = frm.doc.from_warehouse ? 'Warehouse' : 'Company'; let dn = frm.doc.from_warehouse ? frm.doc.from_warehouse : frm.doc.company; frappe.db.get_value(dt, dn, 'default_in_transit_warehouse', (r) => { diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.json b/erpnext/stock/doctype/stock_entry/stock_entry.json index 98c047a09ed..7f945910051 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.json +++ b/erpnext/stock/doctype/stock_entry/stock_entry.json @@ -637,6 +637,8 @@ { "default": "0", "depends_on": "eval: doc.purpose=='Material Transfer' && !doc.outgoing_stock_entry", + "fetch_from": "stock_entry_type.add_to_transit", + "fetch_if_empty": 1, "fieldname": "add_to_transit", "fieldtype": "Check", "label": "Add to Transit", @@ -655,7 +657,7 @@ "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2020-12-09 14:58:13.267321", + "modified": "2021-05-21 11:29:11.917161", "modified_by": "Administrator", "module": "Stock", "name": "Stock Entry", diff --git a/erpnext/stock/doctype/stock_entry_type/stock_entry_type.json b/erpnext/stock/doctype/stock_entry_type/stock_entry_type.json index 0f2b55ec342..eee38be0278 100644 --- a/erpnext/stock/doctype/stock_entry_type/stock_entry_type.json +++ b/erpnext/stock/doctype/stock_entry_type/stock_entry_type.json @@ -6,7 +6,8 @@ "editable_grid": 1, "engine": "InnoDB", "field_order": [ - "purpose" + "purpose", + "add_to_transit" ], "fields": [ { @@ -18,10 +19,17 @@ "options": "\nMaterial Issue\nMaterial Receipt\nMaterial Transfer\nMaterial Transfer for Manufacture\nMaterial Consumption for Manufacture\nManufacture\nRepack\nSend to Subcontractor", "reqd": 1, "set_only_once": 1 + }, + { + "default": "0", + "depends_on": "eval: doc.purpose == 'Material Transfer'", + "fieldname": "add_to_transit", + "fieldtype": "Check", + "label": "Add to Transit" } ], "links": [], - "modified": "2020-08-10 23:24:37.160817", + "modified": "2021-05-21 11:27:01.144110", "modified_by": "Administrator", "module": "Stock", "name": "Stock Entry Type", diff --git a/erpnext/stock/doctype/stock_entry_type/stock_entry_type.py b/erpnext/stock/doctype/stock_entry_type/stock_entry_type.py index a4116aba2c2..1069ec8713e 100644 --- a/erpnext/stock/doctype/stock_entry_type/stock_entry_type.py +++ b/erpnext/stock/doctype/stock_entry_type/stock_entry_type.py @@ -7,4 +7,6 @@ from __future__ import unicode_literals from frappe.model.document import Document class StockEntryType(Document): - pass + def validate(self): + if self.add_to_transit and self.purpose != 'Material Transfer': + self.add_to_transit = 0 From 9979cf5fcc20cf6f267b94bd23a63ce6c4d761c6 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Fri, 21 May 2021 12:12:42 +0530 Subject: [PATCH 062/135] fix: wrong quantity after transaction for parallel stock transactions When two transactions are inserted parallelly then previous SLE could be incorrect for some of them. Locking SLE table would prevent reading from it till transaction is complete. --- 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 9729987d2d3..790318a625c 100644 --- a/erpnext/stock/stock_ledger.py +++ b/erpnext/stock/stock_ledger.py @@ -232,7 +232,8 @@ class update_entries_after(object): and is_cancelled = 0 and timestamp(posting_date, time_format(posting_time, %(time_format)s)) < timestamp(%(posting_date)s, time_format(%(posting_time)s, %(time_format)s)) order by timestamp(posting_date, posting_time) desc, creation desc - limit 1""", args, as_dict=1) + limit 1 + for update""", args, as_dict=1) return sle[0] if sle else frappe._dict() From 4dcac4ae8198ec6e594e1bdfe2408fc33f627940 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Fri, 21 May 2021 13:12:30 +0530 Subject: [PATCH 063/135] refactor(minor): Use identity instead of equality Ignore false positive. --- erpnext/stock/stock_ledger.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py index 790318a625c..b2825fc26f5 100644 --- a/erpnext/stock/stock_ledger.py +++ b/erpnext/stock/stock_ledger.py @@ -624,7 +624,7 @@ class update_entries_after(object): break # If no entry found with outgoing rate, collapse stack - if index == None: + if index is None: # nosemgrep new_stock_value = sum((d[0]*d[1] for d in self.wh_data.stock_queue)) - qty_to_pop*outgoing_rate new_stock_qty = sum((d[0] for d in self.wh_data.stock_queue)) - qty_to_pop self.wh_data.stock_queue = [[new_stock_qty, new_stock_value/new_stock_qty if new_stock_qty > 0 else outgoing_rate]] From 1097dc89c599435ff78d786d24be64c9b383b858 Mon Sep 17 00:00:00 2001 From: Alan <2.alan.tom@gmail.com> Date: Fri, 21 May 2021 14:04:03 +0530 Subject: [PATCH 064/135] fix: show allow zero valuation only when auto checked (#25778) --- .../stock_reconciliation_item.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/stock_reconciliation_item/stock_reconciliation_item.json b/erpnext/stock/doctype/stock_reconciliation_item/stock_reconciliation_item.json index 85c7ebe2634..6bbba051f98 100644 --- a/erpnext/stock/doctype/stock_reconciliation_item/stock_reconciliation_item.json +++ b/erpnext/stock/doctype/stock_reconciliation_item/stock_reconciliation_item.json @@ -1,4 +1,5 @@ { + "actions": [], "creation": "2015-02-17 01:06:05.072764", "doctype": "DocType", "document_type": "Other", @@ -170,6 +171,7 @@ }, { "default": "0", + "depends_on": "allow_zero_valuation_rate", "fieldname": "allow_zero_valuation_rate", "fieldtype": "Check", "label": "Allow Zero Valuation Rate", @@ -179,7 +181,7 @@ ], "istable": 1, "links": [], - "modified": "2021-03-23 11:09:44.407157", + "modified": "2021-05-21 12:13:33.041266", "modified_by": "Administrator", "module": "Stock", "name": "Stock Reconciliation Item", @@ -189,4 +191,4 @@ "sort_field": "modified", "sort_order": "DESC", "track_changes": 1 -} +} \ No newline at end of file From e930456be2e3bea0e7dfbf514470d26cf7e4e4b7 Mon Sep 17 00:00:00 2001 From: Saqib Date: Fri, 21 May 2021 16:31:12 +0530 Subject: [PATCH 065/135] fix(e-invoicing): 'NoneType' object is not iterable (#25781) --- erpnext/regional/india/e_invoice/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/regional/india/e_invoice/utils.py b/erpnext/regional/india/e_invoice/utils.py index 70e6d07eab1..7f25812b47d 100644 --- a/erpnext/regional/india/e_invoice/utils.py +++ b/erpnext/regional/india/e_invoice/utils.py @@ -43,7 +43,7 @@ def validate_eligibility(doc): invalid_supply_type = doc.get('gst_category') not in ['Registered Regular', 'SEZ', 'Overseas', 'Deemed Export'] company_transaction = doc.get('billing_address_gstin') == doc.get('company_gstin') no_taxes_applied = not doc.get('taxes') - has_non_gst_item = any(d for d in doc.get('items') if d.get('is_non_gst')) + has_non_gst_item = any(d for d in doc.get('items', []) if d.get('is_non_gst')) if invalid_company or invalid_supply_type or company_transaction or no_taxes_applied or has_non_gst_item: return False From 0b5e340b6e7f68a41a09cad0ab8dca8105ec905d Mon Sep 17 00:00:00 2001 From: Saqib Date: Fri, 21 May 2021 16:32:56 +0530 Subject: [PATCH 066/135] fix(pos): return case for item with available qty equal to one (#25760) --- .../pos_closing_entry_detail.json | 3 ++- .../accounts/doctype/pos_invoice/pos_invoice.py | 16 +++++----------- .../pos_invoice_merge_log.py | 6 +++--- 3 files changed, 10 insertions(+), 15 deletions(-) diff --git a/erpnext/accounts/doctype/pos_closing_entry_detail/pos_closing_entry_detail.json b/erpnext/accounts/doctype/pos_closing_entry_detail/pos_closing_entry_detail.json index 6e7768dc542..bbf1ba00202 100644 --- a/erpnext/accounts/doctype/pos_closing_entry_detail/pos_closing_entry_detail.json +++ b/erpnext/accounts/doctype/pos_closing_entry_detail/pos_closing_entry_detail.json @@ -46,6 +46,7 @@ "reqd": 1 }, { + "default": "0", "fieldname": "closing_amount", "fieldtype": "Currency", "in_list_view": 1, @@ -57,7 +58,7 @@ "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2020-10-23 16:45:43.662034", + "modified": "2021-05-19 20:08:44.523861", "modified_by": "Administrator", "module": "Accounts", "name": "POS Closing Entry Detail", diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py index 473db565fa5..f55fdab21c3 100644 --- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py +++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py @@ -455,32 +455,26 @@ class POSInvoice(SalesInvoice): @frappe.whitelist() def get_stock_availability(item_code, warehouse): - latest_sle = frappe.db.sql("""select qty_after_transaction - from `tabStock Ledger Entry` + bin_qty = frappe.db.sql("""select actual_qty from `tabBin` where item_code = %s and warehouse = %s - order by posting_date desc, posting_time desc limit 1""", (item_code, warehouse), as_dict=1) pos_sales_qty = get_pos_reserved_qty(item_code, warehouse) - sle_qty = latest_sle[0].qty_after_transaction or 0 if latest_sle else 0 + bin_qty = bin_qty[0].actual_qty or 0 if bin_qty else 0 - if sle_qty and pos_sales_qty: - return sle_qty - pos_sales_qty - else: - return sle_qty + return bin_qty - pos_sales_qty def get_pos_reserved_qty(item_code, warehouse): reserved_qty = frappe.db.sql("""select sum(p_item.qty) as qty from `tabPOS Invoice` p, `tabPOS Invoice Item` p_item where p.name = p_item.parent - and p.consolidated_invoice is NULL - and p.docstatus = 1 + and ifnull(p.consolidated_invoice, '') = '' and p_item.docstatus = 1 and p_item.item_code = %s and p_item.warehouse = %s """, (item_code, warehouse), as_dict=1) - + return reserved_qty[0].qty or 0 if reserved_qty else 0 @frappe.whitelist() diff --git a/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py index bc7874305c0..b0ddea304cd 100644 --- a/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py +++ b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py @@ -56,12 +56,12 @@ class POSInvoiceMergeLog(Document): sales = [d for d in pos_invoice_docs if d.get('is_return') == 0] sales_invoice, credit_note = "", "" - if sales: - sales_invoice = self.process_merging_into_sales_invoice(sales) - if returns: credit_note = self.process_merging_into_credit_note(returns) + if sales: + sales_invoice = self.process_merging_into_sales_invoice(sales) + self.save() # save consolidated_sales_invoice & consolidated_credit_note ref in merge log self.update_pos_invoices(pos_invoice_docs, sales_invoice, credit_note) From b0019bcf5be87ddb88846af76baf018ae532d7aa Mon Sep 17 00:00:00 2001 From: marination Date: Fri, 21 May 2021 21:27:55 +0530 Subject: [PATCH 067/135] fix: Item Variant Details Report Co-authored-by: gavindsouza - Handling of variants with special characters - Set data in appropriately named columns - Code cleanup --- .../item_variant_details.py | 262 +++++++++++------- 1 file changed, 157 insertions(+), 105 deletions(-) diff --git a/erpnext/stock/report/item_variant_details/item_variant_details.py b/erpnext/stock/report/item_variant_details/item_variant_details.py index e8449cc33ec..d8563d79271 100644 --- a/erpnext/stock/report/item_variant_details/item_variant_details.py +++ b/erpnext/stock/report/item_variant_details/item_variant_details.py @@ -14,47 +14,58 @@ def get_data(item): if not item: return [] item_dicts = [] - variants = None - variant_results = frappe.db.sql("""select name from `tabItem` - where variant_of = %s""", item, as_dict=1) + variant_results = frappe.db.get_all( + "Item", + fields=["name"], + filters={ + "variant_of": ["=", item], + "disabled": 0 + } + ) + if not variant_results: - frappe.msgprint(_("There isn't any item variant for the selected item")) + frappe.msgprint(_("There aren't any item variants for the selected item")) return [] else: - variants = ", ".join([frappe.db.escape(variant['name']) for variant in variant_results]) + variant_list = [variant['name'] for variant in variant_results] - order_count_map = get_open_sales_orders_map(variants) - stock_details_map = get_stock_details_map(variants) - buying_price_map = get_buying_price_map(variants) - selling_price_map = get_selling_price_map(variants) - attr_val_map = get_attribute_values_map(variants) + order_count_map = get_open_sales_orders_count(variant_list) + stock_details_map = get_stock_details_map(variant_list) + buying_price_map = get_buying_price_map(variant_list) + selling_price_map = get_selling_price_map(variant_list) + attr_val_map = get_attribute_values_map(variant_list) - attribute_list = [d[0] for d in frappe.db.sql("""select attribute - from `tabItem Variant Attribute` - where parent in ({variants}) group by attribute""".format(variants=variants))] + attributes = frappe.db.get_all( + "Item Variant Attribute", + fields=["attribute"], + filters={ + "parent": ["in", variant_list] + }, + group_by="attribute" + ) + attribute_list = [row.get("attribute") for row in attributes] # Prepare dicts variant_dicts = [{"variant_name": d['name']} for d in variant_results] for item_dict in variant_dicts: - name = item_dict["variant_name"] + name = item_dict.get("variant_name") - for d in attribute_list: - attr_dict = attr_val_map[name] - if attr_dict and attr_dict.get(d): - item_dict[d] = attr_val_map[name][d] + for attribute in attribute_list: + attr_dict = attr_val_map.get(name) + if attr_dict and attr_dict.get(attribute): + item_dict[frappe.scrub(attribute)] = attr_val_map.get(name).get(attribute) - item_dict["Open Orders"] = order_count_map.get(name) or 0 + item_dict["open_orders"] = order_count_map.get(name) or 0 if stock_details_map.get(name): - item_dict["Inventory"] = stock_details_map.get(name)["Inventory"] or 0 - item_dict["In Production"] = stock_details_map.get(name)["In Production"] or 0 - item_dict["Available Selling"] = stock_details_map.get(name)["Available Selling"] or 0 + item_dict["current_stock"] = stock_details_map.get(name)["Inventory"] or 0 + item_dict["in_production"] = stock_details_map.get(name)["In Production"] or 0 else: - item_dict["Inventory"] = item_dict["In Production"] = item_dict["Available Selling"] = 0 + item_dict["current_stock"] = item_dict["in_production"] = 0 - item_dict["Avg. Buying Price List Rate"] = buying_price_map.get(name) or 0 - item_dict["Avg. Selling Price List Rate"] = selling_price_map.get(name) or 0 + item_dict["avg_buying_price_list_rate"] = buying_price_map.get(name) or 0 + item_dict["avg_selling_price_list_rate"] = selling_price_map.get(name) or 0 item_dicts.append(item_dict) @@ -71,117 +82,158 @@ def get_columns(item): item_doc = frappe.get_doc("Item", item) - for d in item_doc.attributes: - columns.append(d.attribute + ":Data:100") + for entry in item_doc.attributes: + columns.append({ + "fieldname": frappe.scrub(entry.attribute), + "label": entry.attribute, + "fieldtype": "Data", + "width": 100 + }) - columns += [_("Avg. Buying Price List Rate") + ":Currency:110", _("Avg. Selling Price List Rate") + ":Currency:110", - _("Inventory") + ":Float:100", _("In Production") + ":Float:100", - _("Open Orders") + ":Float:100", _("Available Selling") + ":Float:100" + additional_columns = [ + { + "fieldname": "avg_buying_price_list_rate", + "label": _("Avg. Buying Price List Rate"), + "fieldtype": "Currency", + "width": 150 + }, + { + "fieldname": "avg_selling_price_list_rate", + "label": _("Avg. Selling Price List Rate"), + "fieldtype": "Currency", + "width": 150 + }, + { + "fieldname": "current_stock", + "label": _("Current Stock"), + "fieldtype": "Float", + "width": 120 + }, + { + "fieldname": "in_production", + "label": _("In Production"), + "fieldtype": "Float", + "width": 150 + }, + { + "fieldname": "open_orders", + "label": _("Open Sales Orders"), + "fieldtype": "Float", + "width": 150 + } ] + columns.extend(additional_columns) return columns -def get_open_sales_orders_map(variants): - open_sales_orders = frappe.db.sql(""" - select - count(*) as count, - item_code - from - `tabSales Order Item` - where - docstatus = 1 and - qty > ifnull(delivered_qty, 0) and - item_code in ({variants}) - group by - item_code - """.format(variants=variants), as_dict=1) +def get_open_sales_orders_count(variants_list): + open_sales_orders = frappe.db.get_list( + "Sales Order", + fields=[ + "name", + "`tabSales Order Item`.item_code" + ], + filters=[ + ["Sales Order", "docstatus", "=", 1], + ["Sales Order Item", "item_code", "in", variants_list] + ], + distinct=1 + ) order_count_map = {} - for d in open_sales_orders: - order_count_map[d["item_code"]] = d["count"] + for row in open_sales_orders: + item_code = row.get("item_code") + if order_count_map.get(item_code) is None: + order_count_map[item_code] = 1 + else: + order_count_map[item_code] += 1 return order_count_map -def get_stock_details_map(variants): - stock_details = frappe.db.sql(""" - select - sum(planned_qty) as planned_qty, - sum(actual_qty) as actual_qty, - sum(projected_qty) as projected_qty, - item_code - from - `tabBin` - where - item_code in ({variants}) - group by - item_code - """.format(variants=variants), as_dict=1) +def get_stock_details_map(variant_list): + stock_details = frappe.db.get_all( + "Bin", + fields=[ + "sum(planned_qty) as planned_qty", + "sum(actual_qty) as actual_qty", + "sum(projected_qty) as projected_qty", + "item_code", + ], + filters={ + "item_code": ["in", variant_list] + }, + group_by="item_code" + ) stock_details_map = {} - for d in stock_details: - name = d["item_code"] + for row in stock_details: + name = row.get("item_code") stock_details_map[name] = { - "Inventory" :d["actual_qty"], - "In Production" :d["planned_qty"], - "Available Selling" :d["projected_qty"] + "Inventory": row.get("actual_qty"), + "In Production": row.get("planned_qty") } return stock_details_map -def get_buying_price_map(variants): - buying = frappe.db.sql(""" - select - avg(price_list_rate) as avg_rate, - item_code - from - `tabItem Price` - where - item_code in ({variants}) and buying=1 - group by - item_code - """.format(variants=variants), as_dict=1) +def get_buying_price_map(variant_list): + buying = frappe.db.get_all( + "Item Price", + fields=[ + "avg(price_list_rate) as avg_rate", + "item_code", + ], + filters={ + "item_code": ["in", variant_list], + "buying": 1 + }, + group_by="item_code" + ) buying_price_map = {} - for d in buying: - buying_price_map[d["item_code"]] = d["avg_rate"] + for row in buying: + buying_price_map[row.get("item_code")] = row.get("avg_rate") return buying_price_map -def get_selling_price_map(variants): - selling = frappe.db.sql(""" - select - avg(price_list_rate) as avg_rate, - item_code - from - `tabItem Price` - where - item_code in ({variants}) and selling=1 - group by - item_code - """.format(variants=variants), as_dict=1) +def get_selling_price_map(variant_list): + selling = frappe.db.get_all( + "Item Price", + fields=[ + "avg(price_list_rate) as avg_rate", + "item_code", + ], + filters={ + "item_code": ["in", variant_list], + "selling": 1 + }, + group_by="item_code" + ) selling_price_map = {} - for d in selling: - selling_price_map[d["item_code"]] = d["avg_rate"] + for row in selling: + selling_price_map[row.get("item_code")] = row.get("avg_rate") return selling_price_map -def get_attribute_values_map(variants): - list_attr = frappe.db.sql(""" - select - attribute, attribute_value, parent - from - `tabItem Variant Attribute` - where - parent in ({variants}) - """.format(variants=variants), as_dict=1) +def get_attribute_values_map(variant_list): + attribute_list = frappe.db.get_all( + "Item Variant Attribute", + fields=[ + "attribute", + "attribute_value", + "parent" + ], + filters={ + "parent": ["in", variant_list] + } + ) attr_val_map = {} - for d in list_attr: - name = d["parent"] + for row in attribute_list: + name = row.get("parent") if not attr_val_map.get(name): attr_val_map[name] = {} - attr_val_map[name][d["attribute"]] = d["attribute_value"] + attr_val_map[name][row.get("attribute")] = row.get("attribute_value") return attr_val_map From e1ab290911cbdfb62b9150e3c85da8567868d8e5 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Sun, 23 May 2021 11:25:35 +0530 Subject: [PATCH 068/135] chore: remove woocommerce package (#25736) This is not used anywhere. It was added in this commit https://github.com/frappe/erpnext/commit/df83148d7ccb15ba18b59c7d9b761a3651bb1dec even there it isn't being used. --- requirements.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index f1ffeb8f481..32da48e9d57 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,4 +10,3 @@ python-youtube~=0.8.0 taxjar~=1.9.2 tweepy~=3.10.0 Unidecode~=1.2.0 -WooCommerce~=3.0.0 From a2d6cf3125fff2ba04e0478021212ffb99777a4f Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Sun, 23 May 2021 18:38:14 +0530 Subject: [PATCH 069/135] chore: remove pytlint config (#25796) - We have flake8 config and it runs in Sider. Flake8 and pylint have huge overlap, no point in using both tools. - The config is not valid pylint config. So it's useless anyway. --- .pylintrc | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .pylintrc diff --git a/.pylintrc b/.pylintrc deleted file mode 100644 index 4b2ea0a5647..00000000000 --- a/.pylintrc +++ /dev/null @@ -1 +0,0 @@ -disable=access-member-before-definition \ No newline at end of file From 7b4a38c71e850223d982c30be2ed448764897c81 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Sun, 23 May 2021 18:49:26 +0530 Subject: [PATCH 070/135] chore: remove print from account controller (#25807) This is polluting test output and it's not useful for debugging without context. --- erpnext/controllers/accounts_controller.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 996c4ed11ba..544e6247251 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -1011,7 +1011,7 @@ 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")) - print(grand_total, base_grand_total) + if total != flt(grand_total, self.precision("grand_total")) or \ base_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")) From 5457db06013792defa1b1ccb58260245eeb932e9 Mon Sep 17 00:00:00 2001 From: krishnagirishp <80564074+krishnagirishp@users.noreply.github.com> Date: Sun, 23 May 2021 21:13:44 +0530 Subject: [PATCH 071/135] chore: remove uses of six.PY2 in codebase (#25062) * remove uses of six.py2 in codebase * changes based on pr feedback * Update amazon_mws_api.py Co-authored-by: Ankush Menat --- .../doctype/amazon_mws_settings/amazon_mws_api.py | 7 ++++--- erpnext/regional/germany/utils/datev/datev_csv.py | 3 +-- erpnext/regional/india/e_invoice/utils.py | 4 +--- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_api.py b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_api.py index f713684d37c..7fd3b34fd5d 100755 --- a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_api.py +++ b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_api.py @@ -7,6 +7,7 @@ from __future__ import unicode_literals import urllib +from urllib.parse import quote import hashlib import hmac import base64 @@ -68,8 +69,9 @@ def calc_md5(string): """ md = hashlib.md5() md.update(string) - return base64.encodestring(md.digest()).strip('\n') if six.PY2 \ - else base64.encodebytes(md.digest()).decode().strip() + return base64.encodebytes(md.digest()).decode().strip() + + def remove_empty(d): """ @@ -177,7 +179,6 @@ class MWS(object): 'SignatureMethod': 'HmacSHA256', } params.update(extra_data) - quote = urllib.quote if six.PY2 else urllib.parse.quote request_description = '&'.join(['%s=%s' % (k, quote(params[k], safe='-_.~')) for k in sorted(params)]) signature = self.calc_signature(method, request_description) url = '%s%s?%s&Signature=%s' % (self.domain, self.uri, request_description, quote(signature)) diff --git a/erpnext/regional/germany/utils/datev/datev_csv.py b/erpnext/regional/germany/utils/datev/datev_csv.py index 826d51f7128..122c15fd811 100644 --- a/erpnext/regional/germany/utils/datev/datev_csv.py +++ b/erpnext/regional/germany/utils/datev/datev_csv.py @@ -55,8 +55,7 @@ def get_datev_csv(data, filters, csv_class): quoting=QUOTE_NONNUMERIC ) - if not six.PY2: - data = data.encode('latin_1', errors='replace') + data = data.encode('latin_1', errors='replace') header = get_header(filters, csv_class) header = ';'.join(header).encode('latin_1', errors='replace') diff --git a/erpnext/regional/india/e_invoice/utils.py b/erpnext/regional/india/e_invoice/utils.py index 7f25812b47d..843fb012b91 100644 --- a/erpnext/regional/india/e_invoice/utils.py +++ b/erpnext/regional/india/e_invoice/utils.py @@ -534,11 +534,9 @@ def santize_einvoice_fields(einvoice): return einvoice def safe_json_load(json_string): - JSONDecodeError = ValueError if six.PY2 else json.JSONDecodeError - try: return json.loads(json_string) - except JSONDecodeError as e: + except json.JSONDecodeError as e: # print a snippet of 40 characters around the location where error occured pos = e.pos start, end = max(0, pos-20), min(len(json_string)-1, pos+20) From ce88c945cd420c001bf786476a62f6e17ebf7692 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Mon, 24 May 2021 11:53:27 +0530 Subject: [PATCH 072/135] Update stock_entry.js --- erpnext/stock/doctype/stock_entry/stock_entry.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js index a40ef001ee9..de23e769f85 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.js +++ b/erpnext/stock/doctype/stock_entry/stock_entry.js @@ -609,11 +609,11 @@ frappe.ui.form.on('Stock Entry', { } }; }; - frm.trigger('set_tansit_warehouse'); + frm.trigger('set_transit_warehouse'); } }, - set_tansit_warehouse: function(frm) { + set_transit_warehouse: function(frm) { if(frm.doc.add_to_transit && frm.doc.purpose == 'Material Transfer' && !frm.doc.to_warehouse && frm.doc.from_warehouse) { let dt = frm.doc.from_warehouse ? 'Warehouse' : 'Company'; @@ -985,7 +985,7 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({ }, from_warehouse: function(doc) { - this.frm.trigger('set_tansit_warehouse'); + this.frm.trigger('set_transit_warehouse'); this.set_warehouse_in_children(doc.items, "s_warehouse", doc.from_warehouse); }, From dc7afa743c20505883df39f3aa7a151a58ef498f Mon Sep 17 00:00:00 2001 From: Jannat Patel <31363128+pateljannat@users.noreply.github.com> Date: Mon, 24 May 2021 17:33:48 +0530 Subject: [PATCH 073/135] fix: profitability test (#25812) * fix: profitability test * fix: replaced class method * fix: removed print statement --- .../project_profitability/test_project_profitability.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/projects/report/project_profitability/test_project_profitability.py b/erpnext/projects/report/project_profitability/test_project_profitability.py index f2b9c2509ad..ea6bdb54ca3 100644 --- a/erpnext/projects/report/project_profitability/test_project_profitability.py +++ b/erpnext/projects/report/project_profitability/test_project_profitability.py @@ -8,7 +8,7 @@ from erpnext.projects.doctype.timesheet.timesheet import make_salary_slip, make_ from erpnext.projects.report.project_profitability.project_profitability import execute class TestProjectProfitability(unittest.TestCase): - @classmethod + def setUp(self): emp = make_employee('test_employee_9@salary.com', company='_Test Company') if not frappe.db.exists('Salary Component', 'Timesheet Component'): @@ -21,7 +21,7 @@ class TestProjectProfitability(unittest.TestCase): self.sales_invoice.due_date = nowdate() self.sales_invoice.submit() - frappe.db.set_value("HR Settings", "HR Settings", "standard_working_hours", 8) + frappe.db.set_value('HR Settings', None, 'standard_working_hours', 8) def test_project_profitability(self): filters = { @@ -55,4 +55,4 @@ class TestProjectProfitability(unittest.TestCase): def tearDown(self): frappe.get_doc("Sales Invoice", self.sales_invoice.name).cancel() frappe.get_doc("Salary Slip", self.salary_slip.name).cancel() - frappe.get_doc("Timesheet", self.timesheet.name).cancel() \ No newline at end of file + frappe.get_doc("Timesheet", self.timesheet.name).cancel() From b6d061fa8c90c678cfd2095577fbe7e3eab1f218 Mon Sep 17 00:00:00 2001 From: Saqib Date: Mon, 24 May 2021 18:22:03 +0530 Subject: [PATCH 074/135] fix(pos): handle db lock timeout error while pos closing (#25813) --- .../pos_invoice_merge_log.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py index b0ddea304cd..08e072e2049 100644 --- a/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py +++ b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py @@ -42,8 +42,9 @@ class POSInvoiceMergeLog(Document): if return_against_status != "Consolidated": # if return entry is not getting merged in the current pos closing and if it is not consolidated bold_unconsolidated = frappe.bold("not Consolidated") - msg = (_("Row #{}: Original Invoice {} of return invoice {} is {}. ") + msg = (_("Row #{}: Original Invoice {} of return invoice {} is {}.") .format(d.idx, bold_return_against, bold_pos_invoice, bold_unconsolidated)) + msg += " " msg += _("Original invoice should be consolidated before or along with the return invoice.") msg += "

" msg += _("You can add original invoice {} manually to proceed.").format(bold_return_against) @@ -274,9 +275,9 @@ def create_merge_logs(invoice_by_customer, closing_entry=None): closing_entry.db_set('error_message', '') closing_entry.update_opening_entry() - except Exception: + except Exception as e: frappe.db.rollback() - message_log = frappe.message_log.pop() + message_log = frappe.message_log.pop() if frappe.message_log else str(e) error_message = safe_load_json(message_log) if closing_entry: @@ -300,9 +301,9 @@ def cancel_merge_logs(merge_logs, closing_entry=None): closing_entry.db_set('error_message', '') closing_entry.update_opening_entry(for_cancel=True) - except Exception: + except Exception as e: frappe.db.rollback() - message_log = frappe.message_log.pop() + message_log = frappe.message_log.pop() if frappe.message_log else str(e) error_message = safe_load_json(message_log) if closing_entry: @@ -348,11 +349,9 @@ def job_already_enqueued(job_name): return True def safe_load_json(message): - JSONDecodeError = ValueError if six.PY2 else json.JSONDecodeError - try: json_message = json.loads(message).get('message') - except JSONDecodeError: + except Exception: json_message = message return json_message \ No newline at end of file From dd5b31f8c45ac78b12f07b6cff31bedffbb68762 Mon Sep 17 00:00:00 2001 From: Saqib Date: Mon, 24 May 2021 18:23:03 +0530 Subject: [PATCH 075/135] fix: set disable rounded total if it is globally enabled (#25789) --- erpnext/setup/doctype/global_defaults/global_defaults.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/setup/doctype/global_defaults/global_defaults.py b/erpnext/setup/doctype/global_defaults/global_defaults.py index e5872171815..a0ba1efb5b4 100644 --- a/erpnext/setup/doctype/global_defaults/global_defaults.py +++ b/erpnext/setup/doctype/global_defaults/global_defaults.py @@ -59,13 +59,15 @@ class GlobalDefaults(Document): # Make property setters to hide rounded total fields for doctype in ("Quotation", "Sales Order", "Sales Invoice", "Delivery Note", - "Supplier Quotation", "Purchase Order", "Purchase Invoice"): + "Supplier Quotation", "Purchase Order", "Purchase Invoice", "Purchase Receipt"): make_property_setter(doctype, "base_rounded_total", "hidden", self.disable_rounded_total, "Check", validate_fields_for_doctype=False) make_property_setter(doctype, "base_rounded_total", "print_hide", 1, "Check", validate_fields_for_doctype=False) make_property_setter(doctype, "rounded_total", "hidden", self.disable_rounded_total, "Check", validate_fields_for_doctype=False) make_property_setter(doctype, "rounded_total", "print_hide", self.disable_rounded_total, "Check", validate_fields_for_doctype=False) + make_property_setter(doctype, "disable_rounded_total", "default", cint(self.disable_rounded_total), "Text", validate_fields_for_doctype=False) + def toggle_in_words(self): self.disable_in_words = cint(self.disable_in_words) From c348215f61abb478fb0ddb64f4ed9b6e251897ff Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Tue, 18 May 2021 08:38:49 +0530 Subject: [PATCH 076/135] fix: Cashlfow mapper not showing data --- erpnext/accounts/report/cash_flow/custom_cash_flow.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/report/cash_flow/custom_cash_flow.py b/erpnext/accounts/report/cash_flow/custom_cash_flow.py index fe2bc725e00..ff87276a876 100644 --- a/erpnext/accounts/report/cash_flow/custom_cash_flow.py +++ b/erpnext/accounts/report/cash_flow/custom_cash_flow.py @@ -165,7 +165,7 @@ def add_data_for_operating_activities( if profit_data: profit_data.update({ "indent": 1, - "parent_account": get_mapper_for(light_mappers, position=0)['section_header'] + "parent_account": get_mapper_for(light_mappers, position=1)['section_header'] }) data.append(profit_data) section_data.append(profit_data) @@ -312,10 +312,10 @@ def add_data_for_other_activities( def compute_data(filters, company_currency, profit_data, period_list, light_mappers, full_mapper): data = [] - operating_activities_mapper = get_mapper_for(light_mappers, position=0) + operating_activities_mapper = get_mapper_for(light_mappers, position=1) other_mappers = [ - get_mapper_for(light_mappers, position=1), - get_mapper_for(light_mappers, position=2) + get_mapper_for(light_mappers, position=2), + get_mapper_for(light_mappers, position=3) ] if operating_activities_mapper: From 25112244ed5c3a4dc62a14bacd5362d3febff356 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Fri, 14 May 2021 21:31:22 +0530 Subject: [PATCH 077/135] fix: Ignore rounding diff while importig JV using data import --- erpnext/accounts/doctype/journal_entry/journal_entry.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index fefab82efc5..ed1bd282235 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -39,7 +39,11 @@ class JournalEntry(AccountsController): self.validate_multi_currency() self.set_amounts_in_company_currency() self.validate_debit_credit_amount() - self.validate_total_debit_and_credit() + + # Do not validate while importing via data import + if not frappe.flags.in_import: + self.validate_total_debit_and_credit() + self.validate_against_jv() self.validate_reference_doc() self.set_against_account() From 5670cf43862d4de29e905e185a25fe9d50b5038c Mon Sep 17 00:00:00 2001 From: Anurag Mishra <32095923+Anurag810@users.noreply.github.com> Date: Mon, 24 May 2021 20:24:20 +0530 Subject: [PATCH 078/135] feat: enhancements in Training Event (#25782) * feat: Some Minor fixes * fix: patch file * fix: patch Co-authored-by: Rucha Mahabal --- .../doctype/training_event/training_event.js | 32 +- .../training_event_employee.json | 301 ++++-------------- .../training_scheduled.json | 8 +- .../training_scheduled/training_scheduled.md | 3 + erpnext/patches.txt | 1 + .../v13_0/set_training_event_attendance.py | 9 + 6 files changed, 113 insertions(+), 241 deletions(-) create mode 100644 erpnext/patches/v13_0/set_training_event_attendance.py diff --git a/erpnext/hr/doctype/training_event/training_event.js b/erpnext/hr/doctype/training_event/training_event.js index 12bc920b187..b7d34b178a0 100644 --- a/erpnext/hr/doctype/training_event/training_event.js +++ b/erpnext/hr/doctype/training_event/training_event.js @@ -2,23 +2,41 @@ // For license information, please see license.txt frappe.ui.form.on('Training Event', { - onload_post_render: function(frm) { + onload_post_render: function (frm) { frm.get_field("employees").grid.set_multiple_add("employee"); }, - refresh: function(frm) { - if(!frm.doc.__islocal) { - frm.add_custom_button(__("Training Result"), function() { + refresh: function (frm) { + if (!frm.doc.__islocal) { + frm.add_custom_button(__("Training Result"), function () { frappe.route_options = { training_event: frm.doc.name - } + }; frappe.set_route("List", "Training Result"); }); - frm.add_custom_button(__("Training Feedback"), function() { + frm.add_custom_button(__("Training Feedback"), function () { frappe.route_options = { training_event: frm.doc.name - } + }; frappe.set_route("List", "Training Feedback"); }); } } }); + +frappe.ui.form.on("Training Event Employee", { + employee: function (frm) { + let emp = []; + for (let d in frm.doc.employees) { + if (frm.doc.employees[d].employee) { + emp.push(frm.doc.employees[d].employee); + } + } + frm.set_query("employee", "employees", function () { + return { + filters: { + name: ["NOT IN", emp] + } + }; + }); + } +}); diff --git a/erpnext/hr/doctype/training_event_employee/training_event_employee.json b/erpnext/hr/doctype/training_event_employee/training_event_employee.json index e3a40649b4d..2d313e9faca 100644 --- a/erpnext/hr/doctype/training_event_employee/training_event_employee.json +++ b/erpnext/hr/doctype/training_event_employee/training_event_employee.json @@ -1,241 +1,80 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "beta": 0, - "creation": "2016-08-08 05:33:39.965305", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 1, + "actions": [], + "creation": "2016-08-08 05:33:39.965305", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "employee", + "employee_name", + "department", + "column_break_3", + "status", + "attendance", + "is_mandatory" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "employee", - "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": "Employee", - "length": 0, - "no_copy": 0, - "options": "Employee", - "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 - }, + "fieldname": "employee", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Employee", + "options": "Employee" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_from": "employee.employee_name", - "fieldname": "employee_name", - "fieldtype": "Read Only", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Employee Name", - "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 - }, + "fetch_from": "employee.employee_name", + "fieldname": "employee_name", + "fieldtype": "Read Only", + "label": "Employee Name" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_from": "employee.department", - "fieldname": "department", - "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": "Department", - "length": 0, - "no_copy": 0, - "options": "Department", - "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 - }, + "fetch_from": "employee.department", + "fieldname": "department", + "fieldtype": "Link", + "label": "Department", + "options": "Department", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_3", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_3", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "Open", - "fieldname": "status", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Status", - "length": 0, - "no_copy": 1, - "options": "Open\nInvited\nCompleted\nFeedback Submitted", - "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_on_submit": 1, + "default": "Open", + "fieldname": "status", + "fieldtype": "Select", + "in_list_view": 1, + "label": "Status", + "no_copy": 1, + "options": "Open\nInvited\nCompleted\nFeedback Submitted" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "attendance", - "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": "Attendance", - "length": 0, - "no_copy": 0, - "options": "Mandatory\nOptional", - "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 + "fieldname": "attendance", + "fieldtype": "Select", + "in_list_view": 1, + "label": "Attendance", + "options": "Present\nAbsent" + }, + { + "columns": 2, + "default": "1", + "fieldname": "is_mandatory", + "fieldtype": "Check", + "in_list_view": 1, + "label": "Is Mandatory" } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 1, - "max_attachments": 0, - "modified": "2019-01-30 11:28:16.170333", - "modified_by": "Administrator", - "module": "HR", - "name": "Training Event Employee", - "name_case": "", - "owner": "Administrator", - "permissions": [], - "quick_entry": 1, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 0, - "track_seen": 0, - "track_views": 0 + ], + "index_web_pages_for_search": 1, + "istable": 1, + "links": [], + "modified": "2021-05-21 12:41:59.336237", + "modified_by": "Administrator", + "module": "HR", + "name": "Training Event Employee", + "owner": "Administrator", + "permissions": [], + "quick_entry": 1, + "sort_field": "modified", + "sort_order": "DESC" } \ No newline at end of file diff --git a/erpnext/hr/notification/training_scheduled/training_scheduled.json b/erpnext/hr/notification/training_scheduled/training_scheduled.json index 966b8875723..e49541e3214 100644 --- a/erpnext/hr/notification/training_scheduled/training_scheduled.json +++ b/erpnext/hr/notification/training_scheduled/training_scheduled.json @@ -11,16 +11,18 @@ "event": "Submit", "idx": 0, "is_standard": 1, - "message": "\n \n \n \n \n \n \n \n
\n
\n {{_(\"Training Event:\")}} {{ doc.event_name }}\n
\n
\n\n\n \n \n \n \n \n \n \n
\n
\n
    \n
  • {{ doc.introduction }}
  • \n
  • {{_(\"Event Location\")}}: {{ doc.location }}
  • \n {% set start = frappe.utils.get_datetime(doc.start_time) %}\n {% set end = frappe.utils.get_datetime(doc.end_time) %}\n {% if start.date() == end.date() %}\n
  • {{_(\"Date\")}}: {{ start.strftime(\"%A, %d %b %Y\") }}
  • \n
  • \n {{_(\"Timing\")}}: {{ start.strftime(\"%I:%M %p\") + ' to ' + end.strftime(\"%I:%M %p\") }}\n
  • \n {% else %}\n
  • {{_(\"Start Time\")}}: {{ start.strftime(\"%A, %d %b %Y at %I:%M %p\") }}\n
  • \n
  • {{_(\"End Time\")}}: {{ end.strftime(\"%A, %d %b %Y at %I:%M %p\") }}\n
  • \n {% endif %}\n
\n {{ _('Event Link') }}: {{ frappe.utils.get_link_to_form(doc.doctype, doc.name) }}\n
\n
", - "modified": "2019-11-29 15:38:31.805409", + "message": "\n \n \n \n \n \n \n \n
\n
\n {{_(\"Training Event:\")}} {{ doc.event_name }}\n
\n
\n\n\n \n \n \n \n \n \n \n
\n
\n {{ doc.introduction }}\n
    \n
  • {{_(\"Event Location\")}}: {{ doc.location }}
  • \n {% set start = frappe.utils.get_datetime(doc.start_time) %}\n {% set end = frappe.utils.get_datetime(doc.end_time) %}\n {% if start.date() == end.date() %}\n
  • {{_(\"Date\")}}: {{ start.strftime(\"%A, %d %b %Y\") }}
  • \n
  • \n {{_(\"Timing\")}}: {{ start.strftime(\"%I:%M %p\") + ' to ' + end.strftime(\"%I:%M %p\") }}\n
  • \n {% else %}\n
  • {{_(\"Start Time\")}}: {{ start.strftime(\"%A, %d %b %Y at %I:%M %p\") }}\n
  • \n
  • {{_(\"End Time\")}}: {{ end.strftime(\"%A, %d %b %Y at %I:%M %p\") }}\n
  • \n {% endif %}\n
  • {{ _('Event Link') }}: {{ frappe.utils.get_link_to_form(doc.doctype, doc.name) }}
  • \n {% if doc.is_mandatory %}\n
  • Note: This Training Event is mandatory
  • \n {% endif %}\n
\n
\n
", + "modified": "2021-05-24 16:29:13.165930", "modified_by": "Administrator", "module": "HR", "name": "Training Scheduled", "owner": "Administrator", "recipients": [ { - "email_by_document_field": "employee_emails" + "receiver_by_document_field": "employee_emails" } ], + "send_system_notification": 0, + "send_to_all_assignees": 0, "subject": "Training Scheduled: {{ doc.name }}" } \ No newline at end of file diff --git a/erpnext/hr/notification/training_scheduled/training_scheduled.md b/erpnext/hr/notification/training_scheduled/training_scheduled.md index 374038ac202..418fd4990e3 100644 --- a/erpnext/hr/notification/training_scheduled/training_scheduled.md +++ b/erpnext/hr/notification/training_scheduled/training_scheduled.md @@ -35,6 +35,9 @@ {% endif %}
  • {{ _('Event Link') }}: {{ frappe.utils.get_link_to_form(doc.doctype, doc.name) }}
  • + {% if doc.is_mandatory %} +
  • Note: This Training Event is mandatory
  • + {% endif %} diff --git a/erpnext/patches.txt b/erpnext/patches.txt index d4655e19b91..1e8ce3c6583 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -780,3 +780,4 @@ erpnext.patches.v13_0.germany_make_custom_fields erpnext.patches.v13_0.germany_fill_debtor_creditor_number erpnext.patches.v13_0.set_pos_closing_as_failed erpnext.patches.v13_0.update_timesheet_changes +erpnext.patches.v13_0.set_training_event_attendance diff --git a/erpnext/patches/v13_0/set_training_event_attendance.py b/erpnext/patches/v13_0/set_training_event_attendance.py new file mode 100644 index 00000000000..18cad8d86c0 --- /dev/null +++ b/erpnext/patches/v13_0/set_training_event_attendance.py @@ -0,0 +1,9 @@ +from __future__ import unicode_literals +import frappe + +def execute(): + frappe.reload_doc('hr', 'doctype', 'training_event') + frappe.reload_doc('hr', 'doctype', 'training_event_employee') + + frappe.db.sql("update `tabTraining Event Employee` set `attendance` = 'Present'") + frappe.db.sql("update `tabTraining Event Employee` set `is_mandatory` = 1 where `attendance` = 'Mandatory'") \ No newline at end of file From b4f0347c02ded2df18156b5a999ca50b82a5ce38 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Mon, 24 May 2021 20:12:24 +0530 Subject: [PATCH 079/135] fix: removed serial no validation for sales invoice --- .../doctype/sales_invoice/sales_invoice.py | 21 ------------------- .../sales_invoice/test_sales_invoice.py | 6 ------ 2 files changed, 27 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index bb74a02606f..1a1f8896571 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -1121,7 +1121,6 @@ class SalesInvoice(SellingController): """ self.set_serial_no_against_delivery_note() self.validate_serial_against_delivery_note() - self.validate_serial_against_sales_invoice() def set_serial_no_against_delivery_note(self): for item in self.items: @@ -1152,26 +1151,6 @@ class SalesInvoice(SellingController): frappe.throw(_("Row {0}: {1} Serial numbers required for Item {2}. You have provided {3}.").format( item.idx, item.qty, item.item_code, len(si_serial_nos))) - def validate_serial_against_sales_invoice(self): - """ check if serial number is already used in other sales invoice """ - for item in self.items: - if not item.serial_no: - continue - - for serial_no in item.serial_no.split("\n"): - serial_no_details = frappe.db.get_value("Serial No", serial_no, - ["sales_invoice", "item_code"], as_dict=1) - - if not serial_no_details: - continue - - if serial_no_details.sales_invoice and serial_no_details.item_code == item.item_code \ - and self.name != serial_no_details.sales_invoice: - sales_invoice_company = frappe.db.get_value("Sales Invoice", serial_no_details.sales_invoice, "company") - if sales_invoice_company == self.company: - frappe.throw(_("Serial Number: {0} is already referenced in Sales Invoice: {1}") - .format(serial_no, serial_no_details.sales_invoice)) - def update_project(self): if self.project: project = frappe.get_doc("Project", self.project) diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 9059d0b0404..df6d4839041 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -933,12 +933,6 @@ class TestSalesInvoice(unittest.TestCase): self.assertFalse(frappe.db.get_value("Serial No", serial_nos[0], "warehouse")) self.assertEqual(frappe.db.get_value("Serial No", serial_nos[0], "delivery_document_no"), si.name) - self.assertEqual(frappe.db.get_value("Serial No", serial_nos[0], "sales_invoice"), - si.name) - - # check if the serial number is already linked with any other Sales Invoice - _si = frappe.copy_doc(si.as_dict()) - self.assertRaises(frappe.ValidationError, _si.insert) return si From 073dcf7e4265539ee521c489202aceb0c38cf84a Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Tue, 25 May 2021 14:06:10 +0530 Subject: [PATCH 080/135] ci(semgrep): fix false positives (#25823) --- .github/helper/semgrep_rules/translate.py | 8 ++++++++ .github/helper/semgrep_rules/translate.yml | 4 ++-- .github/helper/semgrep_rules/ux.js | 9 +++++++++ .github/helper/semgrep_rules/ux.py | 18 ++++++++--------- .github/helper/semgrep_rules/ux.yml | 23 ++++++++++++++++++---- 5 files changed, 47 insertions(+), 15 deletions(-) create mode 100644 .github/helper/semgrep_rules/ux.js diff --git a/.github/helper/semgrep_rules/translate.py b/.github/helper/semgrep_rules/translate.py index bd6cd9126c9..9de6aa94f01 100644 --- a/.github/helper/semgrep_rules/translate.py +++ b/.github/helper/semgrep_rules/translate.py @@ -51,3 +51,11 @@ _(f"what" + f"this is also not cool") _("") # ruleid: frappe-translation-empty-string _('') + + +class Test: + # ok: frappe-translation-python-splitting + def __init__( + args + ): + pass diff --git a/.github/helper/semgrep_rules/translate.yml b/.github/helper/semgrep_rules/translate.yml index fa4ec9e15d0..5f03fb9fd00 100644 --- a/.github/helper/semgrep_rules/translate.yml +++ b/.github/helper/semgrep_rules/translate.yml @@ -44,8 +44,8 @@ rules: pattern-either: - pattern: _(...) + _(...) - pattern: _("..." + "...") - - pattern-regex: '_\([^\)]*\\\s*' # lines broken by `\` - - pattern-regex: '_\(\s*\n' # line breaks allowed by python for using ( ) + - pattern-regex: '[\s\.]_\([^\)]*\\\s*' # lines broken by `\` + - pattern-regex: '[\s\.]_\(\s*\n' # line breaks allowed by python for using ( ) message: | Do not split strings inside translate function. Do not concatenate using translate functions. Please refer: https://frappeframework.com/docs/user/en/translations diff --git a/.github/helper/semgrep_rules/ux.js b/.github/helper/semgrep_rules/ux.js new file mode 100644 index 00000000000..ae73f9cc603 --- /dev/null +++ b/.github/helper/semgrep_rules/ux.js @@ -0,0 +1,9 @@ + +// ok: frappe-missing-translate-function-js +frappe.msgprint('{{ _("Both login and password required") }}'); + +// ruleid: frappe-missing-translate-function-js +frappe.msgprint('What'); + +// ok: frappe-missing-translate-function-js +frappe.throw(' {{ _("Both login and password required") }}. '); diff --git a/.github/helper/semgrep_rules/ux.py b/.github/helper/semgrep_rules/ux.py index 4a744574350..a00d3cd8aef 100644 --- a/.github/helper/semgrep_rules/ux.py +++ b/.github/helper/semgrep_rules/ux.py @@ -2,30 +2,30 @@ import frappe from frappe import msgprint, throw, _ -# ruleid: frappe-missing-translate-function +# ruleid: frappe-missing-translate-function-python throw("Error Occured") -# ruleid: frappe-missing-translate-function +# ruleid: frappe-missing-translate-function-python frappe.throw("Error Occured") -# ruleid: frappe-missing-translate-function +# ruleid: frappe-missing-translate-function-python frappe.msgprint("Useful message") -# ruleid: frappe-missing-translate-function +# ruleid: frappe-missing-translate-function-python msgprint("Useful message") -# ok: frappe-missing-translate-function +# ok: frappe-missing-translate-function-python translatedmessage = _("Hello") -# ok: frappe-missing-translate-function +# ok: frappe-missing-translate-function-python throw(translatedmessage) -# ok: frappe-missing-translate-function +# ok: frappe-missing-translate-function-python msgprint(translatedmessage) -# ok: frappe-missing-translate-function +# ok: frappe-missing-translate-function-python msgprint(_("Helpful message")) -# ok: frappe-missing-translate-function +# ok: frappe-missing-translate-function-python frappe.throw(_("Error occured")) diff --git a/.github/helper/semgrep_rules/ux.yml b/.github/helper/semgrep_rules/ux.yml index ed06a6a80c9..dd667f36c0f 100644 --- a/.github/helper/semgrep_rules/ux.yml +++ b/.github/helper/semgrep_rules/ux.yml @@ -1,15 +1,30 @@ rules: -- id: frappe-missing-translate-function +- id: frappe-missing-translate-function-python pattern-either: - patterns: - pattern: frappe.msgprint("...", ...) - pattern-not: frappe.msgprint(_("..."), ...) - - pattern-not: frappe.msgprint(__("..."), ...) - patterns: - pattern: frappe.throw("...", ...) - pattern-not: frappe.throw(_("..."), ...) - - pattern-not: frappe.throw(__("..."), ...) message: | All user facing text must be wrapped in translate function. Please refer to translation documentation. https://frappeframework.com/docs/user/en/guides/basics/translations - languages: [python, javascript, json] + languages: [python] + severity: ERROR + +- id: frappe-missing-translate-function-js + pattern-either: + - patterns: + - pattern: frappe.msgprint("...", ...) + - pattern-not: frappe.msgprint(__("..."), ...) + # ignore microtemplating e.g. msgprint("{{ _("server side translation") }}") + - pattern-not: frappe.msgprint("=~/\{\{.*\_.*\}\}/i", ...) + - patterns: + - pattern: frappe.throw("...", ...) + - pattern-not: frappe.throw(__("..."), ...) + # ignore microtemplating + - pattern-not: frappe.throw("=~/\{\{.*\_.*\}\}/i", ...) + message: | + All user facing text must be wrapped in translate function. Please refer to translation documentation. https://frappeframework.com/docs/user/en/guides/basics/translations + languages: [javascript] severity: ERROR From 507a211c81c13cf8ea2b2ed401f703d6675b207c Mon Sep 17 00:00:00 2001 From: Rakshith N <36509967+rakshithrddy@users.noreply.github.com> Date: Tue, 25 May 2021 19:03:29 +0530 Subject: [PATCH 081/135] fix: fetch email id from dialog box in pos past order summary' (#25808) --- erpnext/selling/page/point_of_sale/pos_past_order_summary.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/selling/page/point_of_sale/pos_past_order_summary.js b/erpnext/selling/page/point_of_sale/pos_past_order_summary.js index acf4eb371f6..cec831d6166 100644 --- a/erpnext/selling/page/point_of_sale/pos_past_order_summary.js +++ b/erpnext/selling/page/point_of_sale/pos_past_order_summary.js @@ -241,7 +241,7 @@ erpnext.PointOfSale.PastOrderSummary = class { send_email() { const frm = this.events.get_frm(); - const recipients = this.email_dialog.get_values().recipients; + const recipients = this.email_dialog.get_values().email_id; const doc = this.doc || frm.doc; const print_format = frm.pos_print_format; From 6a62ad325f8d5abb350326a14f81a1e6f91db836 Mon Sep 17 00:00:00 2001 From: Laurynas Sakalauskas Date: Tue, 25 May 2021 16:39:44 +0300 Subject: [PATCH 082/135] fix(plaid): withdrawals and deposits are recorded incorrectly (#25784) --- .../doctype/plaid_settings/plaid_settings.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py index 21f1db619e4..ce15e47c5ef 100644 --- a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py +++ b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py @@ -183,11 +183,11 @@ def new_bank_transaction(transaction): bank_account = frappe.db.get_value("Bank Account", dict(integration_id=transaction["account_id"])) if float(transaction["amount"]) >= 0: - debit = float(transaction["amount"]) - credit = 0 - else: debit = 0 - credit = abs(float(transaction["amount"])) + credit = float(transaction["amount"]) + else: + debit = abs(float(transaction["amount"])) + credit = 0 status = "Pending" if transaction["pending"] == "True" else "Settled" From 4d61fa249786f294110afa85e6278ffb5a282b85 Mon Sep 17 00:00:00 2001 From: Afshan <33727827+AfshanKhan@users.noreply.github.com> Date: Tue, 25 May 2021 19:16:02 +0530 Subject: [PATCH 083/135] fix: incorrect cr/dr shown in general ledger for multi-currency transactions (#25654) --- erpnext/accounts/report/utils.py | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/erpnext/accounts/report/utils.py b/erpnext/accounts/report/utils.py index 9de8d19f2a4..b020d0a5062 100644 --- a/erpnext/accounts/report/utils.py +++ b/erpnext/accounts/report/utils.py @@ -81,8 +81,7 @@ def convert_to_presentation_currency(gl_entries, currency_info, company): presentation_currency = currency_info['presentation_currency'] company_currency = currency_info['company_currency'] - pl_accounts = [d.name for d in frappe.get_list('Account', - filters={'report_type': 'Profit and Loss', 'company': company})] + account_currencies = list(set(entry['account_currency'] for entry in gl_entries)) for entry in gl_entries: account = entry['account'] @@ -92,10 +91,15 @@ def convert_to_presentation_currency(gl_entries, currency_info, company): credit_in_account_currency = flt(entry['credit_in_account_currency']) account_currency = entry['account_currency'] - if account_currency != presentation_currency: - value = debit or credit + if len(account_currencies) == 1 and account_currency == presentation_currency: + if entry.get('debit'): + entry['debit'] = debit_in_account_currency - date = entry['posting_date'] if account in pl_accounts else currency_info['report_date'] + if entry.get('credit'): + entry['credit'] = credit_in_account_currency + else: + value = debit or credit + date = currency_info['report_date'] converted_value = convert(value, presentation_currency, company_currency, date) if entry.get('debit'): @@ -104,13 +108,6 @@ def convert_to_presentation_currency(gl_entries, currency_info, company): if entry.get('credit'): entry['credit'] = converted_value - elif account_currency == presentation_currency: - if entry.get('debit'): - entry['debit'] = debit_in_account_currency - - if entry.get('credit'): - entry['credit'] = credit_in_account_currency - converted_gl_list.append(entry) return converted_gl_list From 99636c6aca8a3a0faf6e69f777d75f0d75c3c73b Mon Sep 17 00:00:00 2001 From: Ganga Manoj Date: Tue, 25 May 2021 19:17:01 +0530 Subject: [PATCH 084/135] fix: rearrange buttons for company doctype (#25617) --- erpnext/setup/doctype/company/company.js | 27 ++++++++-------------- erpnext/setup/doctype/company/company.json | 8 +------ 2 files changed, 11 insertions(+), 24 deletions(-) diff --git a/erpnext/setup/doctype/company/company.js b/erpnext/setup/doctype/company/company.js index 9957aad019f..b24048d1cea 100644 --- a/erpnext/setup/doctype/company/company.js +++ b/erpnext/setup/doctype/company/company.js @@ -90,12 +90,6 @@ frappe.ui.form.on("Company", { frm.toggle_enable("default_currency", (frm.doc.__onload && !frm.doc.__onload.transactions_exist)); - if (frm.has_perm('write')) { - frm.add_custom_button(__('Create Tax Template'), function() { - frm.trigger("make_default_tax_template"); - }); - } - if (frappe.perm.has_perm("Cost Center", 0, 'read')) { frm.add_custom_button(__('Cost Centers'), function() { frappe.set_route('Tree', 'Cost Center', {'company': frm.doc.name}); @@ -121,17 +115,21 @@ frappe.ui.form.on("Company", { } if (frm.has_perm('write')) { - frm.add_custom_button(__('Default Tax Template'), function() { + frm.add_custom_button(__('Create Tax Template'), function() { frm.trigger("make_default_tax_template"); - }, __('Create')); + }, __('Manage')); + } + + if (frappe.user.has_role('System Manager')) { + if (frm.has_perm('write')) { + frm.add_custom_button(__('Delete Transactions'), function() { + frm.trigger("delete_company_transactions"); + }, __('Manage')); + } } } erpnext.company.set_chart_of_accounts_options(frm.doc); - - if (!frappe.user.has_role('System Manager')) { - frm.get_field("delete_company_transactions").hide(); - } }, make_default_tax_template: function(frm) { @@ -145,11 +143,6 @@ frappe.ui.form.on("Company", { }) }, - onload_post_render: function(frm) { - if(frm.get_field("delete_company_transactions").$input) - frm.get_field("delete_company_transactions").$input.addClass("btn-danger"); - }, - country: function(frm) { erpnext.company.set_chart_of_accounts_options(frm.doc); }, diff --git a/erpnext/setup/doctype/company/company.json b/erpnext/setup/doctype/company/company.json index 83cbf475abd..061986d92d7 100644 --- a/erpnext/setup/doctype/company/company.json +++ b/erpnext/setup/doctype/company/company.json @@ -99,7 +99,6 @@ "company_description", "registration_info", "registration_details", - "delete_company_transactions", "lft", "rgt", "old_parent" @@ -666,11 +665,6 @@ "oldfieldname": "registration_details", "oldfieldtype": "Code" }, - { - "fieldname": "delete_company_transactions", - "fieldtype": "Button", - "label": "Delete Company Transactions" - }, { "fieldname": "lft", "fieldtype": "Int", @@ -747,7 +741,7 @@ "image_field": "company_logo", "is_tree": 1, "links": [], - "modified": "2021-02-16 15:53:37.167589", + "modified": "2021-05-07 03:11:28.189740", "modified_by": "Administrator", "module": "Setup", "name": "Company", From 18cfced0320f567bd985db050a4260bd3db31331 Mon Sep 17 00:00:00 2001 From: Ganga Manoj Date: Tue, 25 May 2021 19:54:07 +0530 Subject: [PATCH 085/135] fix(Material Request): Make status on list and form view the same (#24856) --- erpnext/controllers/status_updater.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py index ed3aee5c1a1..83d4c331401 100644 --- a/erpnext/controllers/status_updater.py +++ b/erpnext/controllers/status_updater.py @@ -76,12 +76,12 @@ status_map = { ["Stopped", "eval:self.status == 'Stopped'"], ["Cancelled", "eval:self.docstatus == 2"], ["Pending", "eval:self.status != 'Stopped' and self.per_ordered == 0 and self.docstatus == 1"], - ["Partially Ordered", "eval:self.status != 'Stopped' and self.per_ordered < 100 and self.per_ordered > 0 and self.docstatus == 1"], ["Ordered", "eval:self.status != 'Stopped' and self.per_ordered == 100 and self.docstatus == 1 and self.material_request_type == 'Purchase'"], ["Transferred", "eval:self.status != 'Stopped' and self.per_ordered == 100 and self.docstatus == 1 and self.material_request_type == 'Material Transfer'"], ["Issued", "eval:self.status != 'Stopped' and self.per_ordered == 100 and self.docstatus == 1 and self.material_request_type == 'Material Issue'"], ["Received", "eval:self.status != 'Stopped' and self.per_received == 100 and self.docstatus == 1 and self.material_request_type == 'Purchase'"], ["Partially Received", "eval:self.status != 'Stopped' and self.per_received > 0 and self.per_received < 100 and self.docstatus == 1 and self.material_request_type == 'Purchase'"], + ["Partially Ordered", "eval:self.status != 'Stopped' and self.per_ordered < 100 and self.per_ordered > 0 and self.docstatus == 1"], ["Manufactured", "eval:self.status != 'Stopped' and self.per_ordered == 100 and self.docstatus == 1 and self.material_request_type == 'Manufacture'"] ], "Bank Transaction": [ From 81376ea44f8d3afc4db1aad34028ce80eeeed94d Mon Sep 17 00:00:00 2001 From: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> Date: Tue, 25 May 2021 20:39:17 +0530 Subject: [PATCH 086/135] feat: Show net values in Party Accounts (#25714) --- .../report/general_ledger/general_ledger.js | 5 ++++ .../report/general_ledger/general_ledger.py | 27 +++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/erpnext/accounts/report/general_ledger/general_ledger.js b/erpnext/accounts/report/general_ledger/general_ledger.js index fb0d3599261..84f786814de 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.js +++ b/erpnext/accounts/report/general_ledger/general_ledger.js @@ -166,6 +166,11 @@ frappe.query_reports["General Ledger"] = { "fieldname": "show_cancelled_entries", "label": __("Show Cancelled Entries"), "fieldtype": "Check" + }, + { + "fieldname": "show_net_values_in_party_account", + "label": __("Show Net Values in Party Account"), + "fieldtype": "Check" } ] } diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py index b5d7992604f..562df4f6f7d 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.py +++ b/erpnext/accounts/report/general_ledger/general_ledger.py @@ -344,6 +344,9 @@ def get_accountwise_gle(filters, accounting_dimensions, gl_entries, gle_map): consolidated_gle = OrderedDict() group_by = group_by_field(filters.get('group_by')) + if filters.get('show_net_values_in_party_account'): + account_type_map = get_account_type_map(filters.get('company')) + def update_value_in_dict(data, key, gle): data[key].debit += flt(gle.debit) data[key].credit += flt(gle.credit) @@ -351,6 +354,24 @@ def get_accountwise_gle(filters, accounting_dimensions, gl_entries, gle_map): data[key].debit_in_account_currency += flt(gle.debit_in_account_currency) data[key].credit_in_account_currency += flt(gle.credit_in_account_currency) + if filters.get('show_net_values_in_party_account') and \ + account_type_map.get(data[key].account) in ('Receivable', 'Payable'): + net_value = flt(data[key].debit) - flt(data[key].credit) + net_value_in_account_currency = flt(data[key].debit_in_account_currency) \ + - flt(data[key].credit_in_account_currency) + + if net_value < 0: + dr_or_cr = 'credit' + rev_dr_or_cr = 'debit' + else: + dr_or_cr = 'debit' + rev_dr_or_cr = 'credit' + + data[key][dr_or_cr] = abs(net_value) + data[key][dr_or_cr+'_in_account_currency'] = abs(net_value_in_account_currency) + data[key][rev_dr_or_cr] = 0 + data[key][rev_dr_or_cr+'_in_account_currency'] = 0 + if data[key].against_voucher and gle.against_voucher: data[key].against_voucher += ', ' + gle.against_voucher @@ -388,6 +409,12 @@ def get_accountwise_gle(filters, accounting_dimensions, gl_entries, gle_map): return totals, entries +def get_account_type_map(company): + account_type_map = frappe._dict(frappe.get_all('Account', fields=['name', 'account_type'], + filters={'company': company}, as_list=1)) + + return account_type_map + def get_result_as_list(data, filters): balance, balance_in_account_currency = 0, 0 inv_details = get_supplier_invoice_details() From 753e5894de1be99c4e1b9a9fbc3c567b4ae2a5a1 Mon Sep 17 00:00:00 2001 From: Anuja P Date: Thu, 27 May 2021 17:33:22 +0530 Subject: [PATCH 088/135] fix: ageing error in PSOA --- .../process_statement_of_accounts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py index 2ad455c48ff..0b0ee904ff9 100644 --- a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py +++ b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py @@ -94,7 +94,7 @@ def get_report_pdf(doc, consolidated=True): continue html = frappe.render_template(template_path, \ - {"filters": filters, "data": res, "ageing": ageing[0] if doc.include_ageing else None, + {"filters": filters, "data": res, "ageing": ageing[0] if (doc.include_ageing and ageing) else None, "letter_head": letter_head if doc.letter_head else None, "terms_and_conditions": frappe.db.get_value('Terms and Conditions', doc.terms_and_conditions, 'terms') if doc.terms_and_conditions else None}) From 5f4527a6a19c504d1d0d637e8038ba5464b2dab4 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Fri, 28 May 2021 08:55:38 +0530 Subject: [PATCH 089/135] refactor: Use css variables for breakpoint value --- erpnext/public/scss/shopping_cart.scss | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/erpnext/public/scss/shopping_cart.scss b/erpnext/public/scss/shopping_cart.scss index 92e5d32219e..9402cf9ea48 100644 --- a/erpnext/public/scss/shopping_cart.scss +++ b/erpnext/public/scss/shopping_cart.scss @@ -73,15 +73,6 @@ body.product-page { } } - // .card-body { - // text-align: center; - // } - - // .featured-item { - // .card-body { - // text-align: left; - // } - // } .card-img-container { height: 210px; width: 100%; @@ -216,12 +207,12 @@ body.product-page { border-color: var(--table-border-color) !important; padding: 15px; - @media (max-width: 840px) { + @media (max-width: var(--md-width)) { height: 300px; width: 300px; } - @media (min-width: 1090px) { + @media (min-width: var(--lg-width)) { height: 350px; width: 350px; } @@ -233,11 +224,11 @@ body.product-page { .item-slideshow { - @media (max-width: 840px) { + @media (max-width: var(--md-width)) { max-height: 320px; } - @media (min-width: 1090px) { + @media (min-width: var(--lg-width)) { max-height: 430px; } @@ -316,9 +307,6 @@ body.product-page { } .item-group-slideshow { - // .item-group-description { - // max-width: 900px; - // } .carousel-inner.rounded-carousel { border-radius: var(--card-border-radius); From 07ba05630e7e5e96a873a75f38160e108faf6fd8 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Thu, 27 May 2021 15:29:41 +0530 Subject: [PATCH 090/135] fix: Add future in requirements.txt Since future is removed from frappe, adding it as a dependency here --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index f1ffeb8f481..65688f41e0c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ +future==0.18.2 # frappe # https://github.com/frappe/frappe is installed during bench-init gocardless-pro~=1.22.0 googlemaps # used in ERPNext, but dependency is defined in Frappe From f93a7a72c1142068e69cfb01367d16b218e945d0 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Thu, 27 May 2021 15:36:26 +0530 Subject: [PATCH 091/135] ci(test): Temporary change to test PY2 compatability removal in Frappe --- .github/helper/install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/helper/install.sh b/.github/helper/install.sh index 7b0f944c669..8020408904d 100644 --- a/.github/helper/install.sh +++ b/.github/helper/install.sh @@ -12,7 +12,7 @@ sudo apt install npm pip install frappe-bench -git clone https://github.com/frappe/frappe --branch "${GITHUB_BASE_REF:-${GITHUB_REF##*/}}" --depth 1 +git clone https://github.com/gavindsouza/frappe --branch drop-py2-code --depth 1 bench init --skip-assets --frappe-path ~/frappe --python "$(which python)" frappe-bench mkdir ~/frappe-bench/sites/test_site From b084f1d3203b247041695fd50fbc27770eff97d2 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Fri, 28 May 2021 11:57:38 +0530 Subject: [PATCH 092/135] fix(India): Show only company addresses for ITC reversal entry --- .../doctype/journal_entry/regional/india.js | 17 +++++++++++++++++ .../doctype/gstr_3b_report/gstr_3b_report.py | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 erpnext/accounts/doctype/journal_entry/regional/india.js diff --git a/erpnext/accounts/doctype/journal_entry/regional/india.js b/erpnext/accounts/doctype/journal_entry/regional/india.js new file mode 100644 index 00000000000..75a69ac0cf3 --- /dev/null +++ b/erpnext/accounts/doctype/journal_entry/regional/india.js @@ -0,0 +1,17 @@ +frappe.ui.form.on("Journal Entry", { + refresh: function(frm) { + frm.set_query('company_address', function(doc) { + if(!doc.company) { + frappe.throw(__('Please set Company')); + } + + return { + query: 'frappe.contacts.doctype.address.address.address_query', + filters: { + link_doctype: 'Company', + link_name: doc.company + } + }; + }); + } +}); \ No newline at end of file diff --git a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py index 3ddcc58867e..641520437fb 100644 --- a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py +++ b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py @@ -310,7 +310,7 @@ class GSTR3BReport(Document): self.report_dict['sup_details']['osup_det']['txval'] += taxable_value gst_category = self.invoice_detail_map.get(inv, {}).get('gst_category') - place_of_supply = self.invoice_detail_map.get(inv, {}).get('place_of_supply', '00-Other Territory') + place_of_supply = self.invoice_detail_map.get(inv, {}).get('place_of_supply') or '00-Other Territory' if gst_category in ['Unregistered', 'Registered Composition', 'UIN Holders'] and \ self.gst_details.get("gst_state") != place_of_supply.split("-")[1]: From 97687839b0a26251c40994b97eb724e5219163be Mon Sep 17 00:00:00 2001 From: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> Date: Fri, 28 May 2021 13:39:53 +0530 Subject: [PATCH 093/135] ci: Run mariadb tests after PR merge for coverage badge --- .github/workflows/server-tests.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/server-tests.yml b/.github/workflows/server-tests.yml index 92685e2177d..672d96595a7 100644 --- a/.github/workflows/server-tests.yml +++ b/.github/workflows/server-tests.yml @@ -1,6 +1,10 @@ name: Server -on: [pull_request, workflow_dispatch] +on: + pull_request: + workflow_dispatch: + push: + branches: [ develop ] jobs: test: From 49c20f4f8d1913e0eced8e2eb8f9eab9d5bf35c8 Mon Sep 17 00:00:00 2001 From: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> Date: Fri, 28 May 2021 13:41:14 +0530 Subject: [PATCH 094/135] chore: Update server-site test badge URL --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0a556f57b41..c6fc2512445 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@

    ERP made simple

    -[![CI](https://github.com/frappe/erpnext/actions/workflows/ci-tests.yml/badge.svg?branch=develop)](https://github.com/frappe/erpnext/actions/workflows/ci-tests.yml) +[![CI](https://github.com/frappe/erpnext/actions/workflows/server-tests.yml/badge.svg?branch=develop)](https://github.com/frappe/erpnext/actions/workflows/server-tests.yml) [![Open Source Helpers](https://www.codetriage.com/frappe/erpnext/badges/users.svg)](https://www.codetriage.com/frappe/erpnext) [![Coverage Status](https://coveralls.io/repos/github/frappe/erpnext/badge.svg?branch=develop)](https://coveralls.io/github/frappe/erpnext?branch=develop) From 6038663bf82cbfa9e019a6a9020f8ccd92631607 Mon Sep 17 00:00:00 2001 From: Raffael Meyer <14891507+barredterra@users.noreply.github.com> Date: Fri, 28 May 2021 12:59:28 +0200 Subject: [PATCH 095/135] fix: add_deduct_tax in Purchase Taxes setup (#25757) --- erpnext/setup/setup_wizard/operations/taxes_setup.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/setup/setup_wizard/operations/taxes_setup.py b/erpnext/setup/setup_wizard/operations/taxes_setup.py index 429a558c589..50198374417 100644 --- a/erpnext/setup/setup_wizard/operations/taxes_setup.py +++ b/erpnext/setup/setup_wizard/operations/taxes_setup.py @@ -106,6 +106,9 @@ def make_taxes_and_charges_template(company_name, doctype, template): 'charge_type': 'On Net Total' } + if doctype == 'Purchase Taxes and Charges Template': + tax_row_defaults['add_deduct_tax'] = 'Add' + # if account_head is a dict, search or create the account and get it's name if isinstance(account_data, dict): tax_row_defaults['description'] = '{0} @ {1}'.format(account_data.get('account_name'), account_data.get('tax_rate')) From 2df7f474fabab9440336f48de184c6a27d0119c1 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Fri, 28 May 2021 21:12:10 +0530 Subject: [PATCH 096/135] fix: use dictionary filter instead of list (#25875) Item query doesn't support list filter anymore. --- erpnext/manufacturing/doctype/work_order/work_order.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/manufacturing/doctype/work_order/work_order.js b/erpnext/manufacturing/doctype/work_order/work_order.js index a6086fb88da..3e5a72db9a7 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.js +++ b/erpnext/manufacturing/doctype/work_order/work_order.js @@ -76,9 +76,9 @@ frappe.ui.form.on("Work Order", { frm.set_query("production_item", function() { return { query: "erpnext.controllers.queries.item_query", - filters:[ - ['is_stock_item', '=',1] - ] + filters: { + "is_stock_item": 1, + } }; }); From 62996ec980fa23e0b4c58a8f8286904109e44bdc Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Fri, 28 May 2021 23:06:15 +0530 Subject: [PATCH 097/135] Revert "ci(test): Temporary change to test PY2 compatability removal in Frappe" This reverts commit f93a7a72c1142068e69cfb01367d16b218e945d0. --- .github/helper/install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/helper/install.sh b/.github/helper/install.sh index 8020408904d..7b0f944c669 100644 --- a/.github/helper/install.sh +++ b/.github/helper/install.sh @@ -12,7 +12,7 @@ sudo apt install npm pip install frappe-bench -git clone https://github.com/gavindsouza/frappe --branch drop-py2-code --depth 1 +git clone https://github.com/frappe/frappe --branch "${GITHUB_BASE_REF:-${GITHUB_REF##*/}}" --depth 1 bench init --skip-assets --frappe-path ~/frappe --python "$(which python)" frappe-bench mkdir ~/frappe-bench/sites/test_site From 05d5fb24f7bdb3c4f7dd069590447b8d5752de70 Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Sat, 29 May 2021 23:18:36 +0530 Subject: [PATCH 098/135] fix(test): tax detail report (#25884) --- erpnext/accounts/report/tax_detail/test_tax_detail.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/report/tax_detail/test_tax_detail.py b/erpnext/accounts/report/tax_detail/test_tax_detail.py index d3b8de5d191..743ddba0240 100644 --- a/erpnext/accounts/report/tax_detail/test_tax_detail.py +++ b/erpnext/accounts/report/tax_detail/test_tax_detail.py @@ -71,10 +71,8 @@ class TestTaxDetail(unittest.TestCase): def rm_testdocs(self): "Remove the Company and all data" - from erpnext.setup.doctype.company.delete_company_transactions import delete_company_transactions - delete_company_transactions(self.company.name) - self.company.delete() - + from erpnext.setup.doctype.company.company import create_transaction_deletion_request + create_transaction_deletion_request(self.company.name) def test_report(self): self.load_testdocs() From 4c94ccc8d8f01715a9a2109c4c9142000fe34c5a Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 31 May 2021 10:51:57 +0530 Subject: [PATCH 099/135] chore: Added change log --- erpnext/change_log/v13/v13_4_0.md | 54 +++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 erpnext/change_log/v13/v13_4_0.md diff --git a/erpnext/change_log/v13/v13_4_0.md b/erpnext/change_log/v13/v13_4_0.md new file mode 100644 index 00000000000..eaf4f762d49 --- /dev/null +++ b/erpnext/change_log/v13/v13_4_0.md @@ -0,0 +1,54 @@ +# Version 13.4.0 Release Notes + +### Features & Enhancements + +- Multiple GST enhancement and fixes ([#25249](https://github.com/frappe/erpnext/pull/25249)) +- Linking supplier with an item group for filtering items ([#25683](https://github.com/frappe/erpnext/pull/25683)) +- Leave Policy Assignment Refactor ([#24327](https://github.com/frappe/erpnext/pull/24327)) +- Dimension-wise Accounts Balance Report ([#25260](https://github.com/frappe/erpnext/pull/25260)) +- Show net values in Party Accounts ([#25714](https://github.com/frappe/erpnext/pull/25714)) +- Add pending qty section to batch/serial selector dialog ([#25519](https://github.com/frappe/erpnext/pull/25519)) +- enhancements in Training Event ([#25782](https://github.com/frappe/erpnext/pull/25782)) +- Refactored timesheet ([#25701](https://github.com/frappe/erpnext/pull/25701)) + +### Fixes + +- Process Statement of Accounts formatting ([#25777](https://github.com/frappe/erpnext/pull/25777)) +- Removed serial no validation for sales invoice ([#25817](https://github.com/frappe/erpnext/pull/25817)) +- Fetch email id from dialog box in pos past order summary ([#25808](https://github.com/frappe/erpnext/pull/25808)) +- Don't map set warehouse from delivery note to purchase receipt ([#25672](https://github.com/frappe/erpnext/pull/25672)) +- Apply permission while selecting projects ([#25765](https://github.com/frappe/erpnext/pull/25765)) +- Error on adding bank account to plaid ([#25658](https://github.com/frappe/erpnext/pull/25658)) +- Set disable rounded total if it is globally enabled ([#25789](https://github.com/frappe/erpnext/pull/25789)) +- Wrong amount on CR side in general ledger report for customer when different account currencies are involved ([#25654](https://github.com/frappe/erpnext/pull/25654)) +- Stock move dialog duplicate submit actions (V13) ([#25486](https://github.com/frappe/erpnext/pull/25486)) +- Cashflow mapper not showing data ([#25815](https://github.com/frappe/erpnext/pull/25815)) +- Ignore rounding diff while importing JV using data import ([#25816](https://github.com/frappe/erpnext/pull/25816)) +- Woocommerce order sync issue ([#25688](https://github.com/frappe/erpnext/pull/25688)) +- Expected amount in pos closing payments table ([#25737](https://github.com/frappe/erpnext/pull/25737)) +- Show only company addresses for ITC reversal entry ([#25867](https://github.com/frappe/erpnext/pull/25867)) +- Timeout error while loading warehouse tree ([#25694](https://github.com/frappe/erpnext/pull/25694)) +- Plaid Withdrawals and Deposits are recorded incorrectly ([#25784](https://github.com/frappe/erpnext/pull/25784)) +- Return case for item with available qty equal to one ([#25760](https://github.com/frappe/erpnext/pull/25760)) +- The status of repost item valuation showing In Progress since long time ([#25754](https://github.com/frappe/erpnext/pull/25754)) +- Updated applicable charges form in landed cost voucher ([#25732](https://github.com/frappe/erpnext/pull/25732)) +- Rearrange buttons for Company DocType ([#25617](https://github.com/frappe/erpnext/pull/25617)) +- Show uom for item in selector dialog ([#25697](https://github.com/frappe/erpnext/pull/25697)) +- Warehouse not found in stock entry ([#25776](https://github.com/frappe/erpnext/pull/25776)) +- Use dictionary filter instead of list (bp #25874 pre-release) ([#25875](https://github.com/frappe/erpnext/pull/25875)) +- Send emails on rfq submit ([#25695](https://github.com/frappe/erpnext/pull/25695)) +- Cannot bypass e-invoicing for non gst item invoices ([#25759](https://github.com/frappe/erpnext/pull/25759)) +- Validation message of quality inspection in purchase receipt ([#25666](https://github.com/frappe/erpnext/pull/25666)) +- Dialog variable assignment after definition in POS ([#25681](https://github.com/frappe/erpnext/pull/25681)) +- Wrong quantity after transaction for parallel stock transactions ([#25779](https://github.com/frappe/erpnext/pull/25779)) +- Item Variant Details Report ([#25797](https://github.com/frappe/erpnext/pull/25797)) +- Duplicate stock entry on multiple click ([#25742](https://github.com/frappe/erpnext/pull/25742)) +- Bank statement import via google sheet ([#25676](https://github.com/frappe/erpnext/pull/25676)) +- Change today to now to get data for reposting ([#25702](https://github.com/frappe/erpnext/pull/25702)) +- Parameter for get_filtered_list_for_consolidated_report in consolidated balance sheet ([#25698](https://github.com/frappe/erpnext/pull/25698)) +- Ageing error in PSOA ([#25857](https://github.com/frappe/erpnext/pull/25857)) +- Breaking cost center validation ([#25660](https://github.com/frappe/erpnext/pull/25660)) +- Project filter for Kanban Board ([#25744](https://github.com/frappe/erpnext/pull/25744)) +- Show allow zero valuation only when auto checked ([#25778](https://github.com/frappe/erpnext/pull/25778)) +- Missing cost center message on creating gl entries ([#25755](https://github.com/frappe/erpnext/pull/25755)) +- Address template with upper filter throws jinja error ([#25756](https://github.com/frappe/erpnext/pull/25756)) From c63e233bc7d60ae71f211ec79747ab39eaa827aa Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 31 May 2021 11:34:33 +0550 Subject: [PATCH 100/135] bumped to version 13.4.0 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 8d1767497f4..20097ef066e 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__ = '13.3.1' +__version__ = '13.4.0' def get_default_company(user=None): '''Get default company for user''' From 0358b6474368462690211a0191138b644c3bd3be Mon Sep 17 00:00:00 2001 From: Anupam Date: Mon, 31 May 2021 15:59:32 +0530 Subject: [PATCH 101/135] fix: featching serialized items --- .../stock_reconciliation/stock_reconciliation.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py index 7e216d61818..32e0ccb93f9 100644 --- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py +++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py @@ -477,19 +477,19 @@ class StockReconciliation(StockController): def get_items(warehouse, posting_date, posting_time, company): lft, rgt = frappe.db.get_value("Warehouse", warehouse, ["lft", "rgt"]) items = frappe.db.sql(""" - select i.name, i.item_name, bin.warehouse + select i.name, i.item_name, bin.warehouse, i.has_serial_no from tabBin bin, tabItem i where i.name=bin.item_code and i.disabled=0 and i.is_stock_item = 1 - and i.has_variants = 0 and i.has_serial_no = 0 and i.has_batch_no = 0 + and i.has_variants = 0 and i.has_batch_no = 0 and exists(select name from `tabWarehouse` where lft >= %s and rgt <= %s and name=bin.warehouse) """, (lft, rgt)) items += frappe.db.sql(""" - select i.name, i.item_name, id.default_warehouse + select i.name, i.item_name, id.default_warehouse, i.has_serial_no from tabItem i, `tabItem Default` id where i.name = id.parent and exists(select name from `tabWarehouse` where lft >= %s and rgt <= %s and name=id.default_warehouse) - and i.is_stock_item = 1 and i.has_serial_no = 0 and i.has_batch_no = 0 + and i.is_stock_item = 1 and i.has_batch_no = 0 and i.has_variants = 0 and i.disabled = 0 and id.company=%s group by i.name """, (lft, rgt, company)) @@ -497,7 +497,7 @@ def get_items(warehouse, posting_date, posting_time, company): res = [] for d in set(items): stock_bal = get_stock_balance(d[0], d[2], posting_date, posting_time, - with_valuation_rate=True) + with_valuation_rate=True , with_serial_no=cint(d[3])) if frappe.db.get_value("Item", d[0], "disabled") == 0: res.append({ @@ -507,7 +507,9 @@ def get_items(warehouse, posting_date, posting_time, company): "item_name": d[1], "valuation_rate": stock_bal[1], "current_qty": stock_bal[0], - "current_valuation_rate": stock_bal[1] + "current_valuation_rate": stock_bal[1], + "current_serial_no": stock_bal[2] if cint(d[3]) else '', + "serial_no": stock_bal[2] if cint(d[3]) else '' }) return res From 5b17f335d1da606f131bf6605f81af0a83bfb864 Mon Sep 17 00:00:00 2001 From: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> Date: Tue, 1 Jun 2021 08:18:56 +0530 Subject: [PATCH 102/135] ci: Add coveralls_repo_token env variable --- .github/workflows/server-tests.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/server-tests.yml b/.github/workflows/server-tests.yml index 672d96595a7..69afa15187d 100644 --- a/.github/workflows/server-tests.yml +++ b/.github/workflows/server-tests.yml @@ -91,6 +91,7 @@ jobs: coveralls env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_TOKEN }} COVERALLS_FLAG_NAME: run-${{ matrix.container }} COVERALLS_SERVICE_NAME: ${{ github.event_name == 'pull_request' && 'github' || 'github-actions' }} COVERALLS_PARALLEL: true From eff8f6fe34d5571795b1e5f037529c10c1744d04 Mon Sep 17 00:00:00 2001 From: Sagar Vora Date: Tue, 1 Jun 2021 19:57:17 +0530 Subject: [PATCH 103/135] fix(Payroll): no need to set `abbr` specially in Salary Slip (#25877) --- erpnext/payroll/doctype/salary_slip/salary_slip.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/erpnext/payroll/doctype/salary_slip/salary_slip.py b/erpnext/payroll/doctype/salary_slip/salary_slip.py index afdf081ac89..3c2533131b9 100644 --- a/erpnext/payroll/doctype/salary_slip/salary_slip.py +++ b/erpnext/payroll/doctype/salary_slip/salary_slip.py @@ -621,16 +621,13 @@ class SalarySlip(TransactionBase): component_row = self.append(component_type) for attr in ( - 'depends_on_payment_days', 'salary_component', + 'depends_on_payment_days', 'salary_component', 'abbr', 'do_not_include_in_total', 'is_tax_applicable', 'is_flexible_benefit', 'variable_based_on_taxable_salary', 'exempted_from_income_tax' ): component_row.set(attr, component_data.get(attr)) - abbr = component_data.get('abbr') or component_data.get('salary_component_abbr') - component_row.set('abbr', abbr) - if additional_salary: component_row.default_amount = 0 component_row.additional_amount = amount From 5dd92934aef8dfe89555560ff5b9680596d33bff Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Wed, 2 Jun 2021 14:13:09 +0530 Subject: [PATCH 104/135] fix: not able to select the item code in work order --- erpnext/controllers/queries.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py index 46301b7587d..638503edfa9 100644 --- a/erpnext/controllers/queries.py +++ b/erpnext/controllers/queries.py @@ -204,7 +204,7 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals if "description" in searchfields: searchfields.remove("description") - + columns = '' extra_searchfields = [field for field in searchfields if not field in ["name", "item_group", "description"]] @@ -216,9 +216,10 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals if not field in searchfields] searchfields = " or ".join([field + " like %(txt)s" for field in searchfields]) - if filters.get('supplier'): - item_group_list = frappe.get_all('Supplier Item Group', filters = {'supplier': filters.get('supplier')}, fields = ['item_group']) - + if filters and isinstance(filters, dict) and filters.get('supplier'): + item_group_list = frappe.get_all('Supplier Item Group', + filters = {'supplier': filters.get('supplier')}, fields = ['item_group']) + item_groups = [] for i in item_group_list: item_groups.append(i.item_group) @@ -227,7 +228,7 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals if item_groups: filters['item_group'] = ['in', item_groups] - + description_cond = '' if frappe.db.count('Item', cache=True) < 50000: # scan description only if items are less than 50000 From 8821d71094729ba0ce576414486d0fcf91035f0e Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Wed, 2 Jun 2021 22:34:19 +0550 Subject: [PATCH 105/135] bumped to version 13.4.1 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 20097ef066e..5808090db35 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__ = '13.4.0' +__version__ = '13.4.1' def get_default_company(user=None): '''Get default company for user''' From f899b3a633f7d43e3b44c17ad69e300298e7ba95 Mon Sep 17 00:00:00 2001 From: Anoop <3326959+akurungadam@users.noreply.github.com> Date: Thu, 3 Jun 2021 09:24:31 +0530 Subject: [PATCH 106/135] fix: update linked Customer on Patient update only if Link Customer to Patient is enabled (#25921) --- erpnext/healthcare/doctype/patient/patient.py | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/erpnext/healthcare/doctype/patient/patient.py b/erpnext/healthcare/doctype/patient/patient.py index 789d452c070..56a34007ffb 100644 --- a/erpnext/healthcare/doctype/patient/patient.py +++ b/erpnext/healthcare/doctype/patient/patient.py @@ -33,21 +33,20 @@ class Patient(Document): self.reload() # self.notify_update() def on_update(self): - if self.customer: - customer = frappe.get_doc('Customer', self.customer) - if self.customer_group: - customer.customer_group = self.customer_group - if self.territory: - customer.territory = self.territory - - customer.customer_name = self.patient_name - customer.default_price_list = self.default_price_list - customer.default_currency = self.default_currency - customer.language = self.language - customer.ignore_mandatory = True - customer.save(ignore_permissions=True) - else: - if frappe.db.get_single_value('Healthcare Settings', 'link_customer_to_patient'): + if frappe.db.get_single_value('Healthcare Settings', 'link_customer_to_patient'): + if self.customer: + customer = frappe.get_doc('Customer', self.customer) + if self.customer_group: + customer.customer_group = self.customer_group + if self.territory: + customer.territory = self.territory + customer.customer_name = self.patient_name + customer.default_price_list = self.default_price_list + customer.default_currency = self.default_currency + customer.language = self.language + customer.ignore_mandatory = True + customer.save(ignore_permissions=True) + else: create_customer(self) def set_full_name(self): From 3e920892001856ce8157d44778cae618a2a4babf Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Fri, 4 Jun 2021 11:15:38 +0530 Subject: [PATCH 107/135] fix: invalid 'depends_on' expression in opportunity (#25953) --- erpnext/crm/doctype/opportunity/opportunity.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/erpnext/crm/doctype/opportunity/opportunity.json b/erpnext/crm/doctype/opportunity/opportunity.json index 2e09a76c0f6..4ba41402449 100644 --- a/erpnext/crm/doctype/opportunity/opportunity.json +++ b/erpnext/crm/doctype/opportunity/opportunity.json @@ -280,7 +280,6 @@ "read_only": 1 }, { - "depends_on": "eval:", "fieldname": "territory", "fieldtype": "Link", "label": "Territory", @@ -431,7 +430,7 @@ "icon": "fa fa-info-sign", "idx": 195, "links": [], - "modified": "2021-01-06 19:42:46.190051", + "modified": "2021-06-04 10:11:22.831139", "modified_by": "Administrator", "module": "CRM", "name": "Opportunity", From 5bf5775b4373c84d3834f56cdc568f952798024b Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Fri, 4 Jun 2021 11:44:40 +0530 Subject: [PATCH 108/135] chore: Drop old patches v7 backup was restored and upgraded to latest v10.x.x branch. The patches run uptil the upgrade are removed in this change. This means only existing v10 sites are allowed direct upgrade to v13 and newer --- erpnext/patches/repair_tools/__init__.py | 0 .../set_stock_balance_as_per_serial_no.py | 13 - erpnext/patches/v10_0/__init__.py | 0 .../patches/v10_0/add_agriculture_domain.py | 13 - .../add_guardian_role_for_parent_portal.py | 23 -- .../patches/v10_0/add_non_profit_domain.py | 20 -- .../allow_operators_in_supplier_scorecard.py | 23 -- .../v10_0/copy_projects_renamed_fields.py | 13 - ..._regional_print_format_based_on_country.py | 22 -- .../fix_reserved_qty_for_sub_contract.py | 31 --- .../recalculate_gross_margin_for_project.py | 14 - .../v10_0/rename_schools_to_education.py | 32 --- ...r_purchase_receipts_with_rejected_items.py | 32 --- ...t_requested_qty_for_non_stock_uom_items.py | 21 -- ...t_auto_created_serial_no_in_stock_entry.py | 56 ---- erpnext/patches/v10_0/set_b2c_limit.py | 12 - ..._default_payment_terms_based_on_company.py | 37 --- erpnext/patches/v10_0/set_discount_amount.py | 35 --- ...set_numeric_ranges_in_template_if_blank.py | 35 --- .../v10_0/set_primary_contact_for_customer.py | 21 -- ...n_transactions_based_on_serial_no_input.py | 21 -- .../patches/v10_0/set_student_party_type.py | 8 - .../setup_vat_for_uae_and_saudi_arabia.py | 13 - ...s_of_all_department_members_in_calendar.py | 6 - erpnext/patches/v10_0/taxes_issue_with_pos.py | 26 -- .../update_address_template_for_india.py | 12 - .../patches/v10_0/update_assessment_plan.py | 17 -- .../patches/v10_0/update_assessment_result.py | 20 -- .../update_asset_calculate_depreciation.py | 12 - .../v10_0/update_hub_connector_domain.py | 10 - .../v10_0/update_lft_rgt_for_employee.py | 9 - .../patches/v10_0/update_project_in_sle.py | 15 -- .../update_reserved_qty_for_purchase_order.py | 53 ---- ...date_sales_order_link_to_purchase_order.py | 18 -- ...update_status_for_multiple_source_in_po.py | 40 --- .../update_status_in_purchase_receipt.py | 8 - .../update_territory_and_customer_group.py | 29 --- .../v10_0/update_user_image_in_employee.py | 19 -- .../v10_0/update_warehouse_address_details.py | 37 --- erpnext/patches/v10_1/__init__.py | 0 erpnext/patches/v11_0/__init__.py | 1 - .../v11_0/remove_subscriber_doctype.py | 16 -- erpnext/patches/v11_1/__init__.py | 0 erpnext/patches/v12_0/__init__.py | 0 erpnext/patches/v13_0/__init__.py | 1 - erpnext/patches/v4_0/__init__.py | 0 .../patches/v4_0/apply_user_permissions.py | 50 ---- erpnext/patches/v4_0/countrywise_coa.py | 29 --- ...custom_fields_for_india_specific_fields.py | 63 ----- .../v4_0/create_price_list_if_missing.py | 35 --- .../v4_0/customer_discount_to_pricing_rule.py | 33 --- erpnext/patches/v4_0/fields_to_be_renamed.py | 109 -------- erpnext/patches/v4_0/fix_address_template.py | 12 - .../patches/v4_0/fix_case_of_hr_module_def.py | 13 - erpnext/patches/v4_0/fix_contact_address.py | 13 - erpnext/patches/v4_0/fix_employee_user_id.py | 23 -- .../global_defaults_to_system_settings.py | 39 --- erpnext/patches/v4_0/import_country_codes.py | 15 -- .../v4_0/map_charge_to_taxes_and_charges.py | 16 -- .../move_warehouse_user_to_restrictions.py | 13 - erpnext/patches/v4_0/new_address_template.py | 14 - .../patches/v4_0/reload_sales_print_format.py | 8 - .../remove_employee_role_if_no_employee.py | 18 -- .../patches/v4_0/remove_module_home_pages.py | 10 - .../patches/v4_0/rename_sitemap_to_route.py | 17 -- .../v4_0/reset_permissions_for_masters.py | 20 -- .../patches/v4_0/save_default_letterhead.py | 13 - .../set_pricing_rule_for_buying_or_selling.py | 13 - erpnext/patches/v4_0/split_email_settings.py | 67 ----- .../patches/v4_0/update_account_root_type.py | 34 --- ...custom_print_formats_for_renamed_fields.py | 36 --- ...to_sales_person_in_maintenance_schedule.py | 12 - ...harges_in_custom_purchase_print_formats.py | 12 - .../v4_0/update_tax_amount_after_discount.py | 20 -- .../patches/v4_0/update_user_properties.py | 51 ---- .../v4_0/update_users_report_view_settings.py | 12 - erpnext/patches/v4_0/validate_v3_patch.py | 11 - erpnext/patches/v4_1/__init__.py | 0 .../v4_1/fix_delivery_and_billing_status.py | 12 - erpnext/patches/v4_1/fix_jv_remarks.py | 21 -- .../v4_1/fix_sales_order_delivered_status.py | 15 -- .../patches/v4_1/set_outgoing_email_footer.py | 12 - erpnext/patches/v4_2/__init__.py | 0 .../patches/v4_2/add_currency_turkish_lira.py | 10 - erpnext/patches/v4_2/default_website_style.py | 11 - ...elete_gl_entries_for_cancelled_invoices.py | 14 - .../patches/v4_2/delete_old_print_formats.py | 23 -- erpnext/patches/v4_2/discount_amount.py | 12 - .../patches/v4_2/fix_account_master_type.py | 12 - .../fix_gl_entries_for_stock_transactions.py | 54 ---- erpnext/patches/v4_2/fix_recurring_orders.py | 41 --- erpnext/patches/v4_2/party_model.py | 117 --------- erpnext/patches/v4_2/recalculate_bom_cost.py | 16 -- .../repost_sle_for_si_with_no_warehouse.py | 34 --- .../v4_2/repost_stock_reconciliation.py | 31 --- erpnext/patches/v4_2/reset_bom_costs.py | 17 -- .../v4_2/seprate_manufacture_and_repack.py | 9 - erpnext/patches/v4_2/set_company_country.py | 15 -- erpnext/patches/v4_2/set_item_has_batch.py | 65 ----- erpnext/patches/v4_2/toggle_rounded_total.py | 9 - .../v4_2/update_landed_cost_voucher.py | 10 - .../patches/v4_2/update_project_milestones.py | 9 - .../update_sales_order_invoice_field_name.py | 7 - .../v4_2/update_stock_uom_for_dn_in_sle.py | 11 - erpnext/patches/v4_4/__init__.py | 0 erpnext/patches/v4_4/make_email_accounts.py | 96 ------- erpnext/patches/v5_0/__init__.py | 0 .../v5_0/convert_stock_reconciliation.py | 31 --- .../patches/v5_0/execute_on_doctype_update.py | 9 - .../fix_taxes_and_totals_in_party_currency.py | 66 ----- .../v5_0/index_on_account_and_gl_entry.py | 30 --- erpnext/patches/v5_0/is_group.py | 9 - erpnext/patches/v5_0/item_patches.py | 6 - .../v5_0/link_warehouse_with_account.py | 10 - erpnext/patches/v5_0/new_crm_module.py | 24 -- erpnext/patches/v5_0/newsletter.py | 38 --- .../v5_0/opportunity_not_submittable.py | 10 - erpnext/patches/v5_0/party_model_patch_fix.py | 18 -- erpnext/patches/v5_0/portal_fixes.py | 7 - erpnext/patches/v5_0/project_costing.py | 8 - .../v5_0/recalculate_total_amount_in_jv.py | 26 -- ...nned_operating_cost_in_production_order.py | 13 - .../patches/v5_0/remove_birthday_events.py | 7 - erpnext/patches/v5_0/rename_customer_issue.py | 6 - erpnext/patches/v5_0/rename_pos_setting.py | 6 - .../patches/v5_0/rename_table_fieldnames.py | 243 ------------------ .../v5_0/rename_taxes_and_charges_master.py | 14 - erpnext/patches/v5_0/rename_total_fields.py | 55 ---- ...lds_in_custom_scripts_and_print_formats.py | 65 ----- .../repost_gle_for_jv_with_multiple_party.py | 26 -- erpnext/patches/v5_0/repost_requested_qty.py | 21 -- erpnext/patches/v5_0/reset_values_in_tools.py | 12 - erpnext/patches/v5_0/set_appraisal_remarks.py | 9 - .../v5_0/set_default_company_in_bom.py | 10 - erpnext/patches/v5_0/set_footer_address.py | 9 - .../patches/v5_0/stock_entry_update_value.py | 8 - .../taxes_and_totals_in_party_currency.py | 80 ------ erpnext/patches/v5_0/update_account_types.py | 20 -- erpnext/patches/v5_0/update_advance_paid.py | 13 - .../update_companywise_payment_account.py | 21 -- .../v5_0/update_dn_against_doc_fields.py | 14 - erpnext/patches/v5_0/update_from_bom.py | 9 - .../update_frozen_accounts_permission_role.py | 13 - .../v5_0/update_item_and_description_again.py | 50 ---- .../v5_0/update_item_desc_in_invoice.py | 52 ---- .../v5_0/update_item_description_and_image.py | 54 ---- .../patches/v5_0/update_item_name_in_bom.py | 18 -- .../v5_0/update_journal_entry_title.py | 12 - ...pdate_material_transfer_for_manufacture.py | 6 - ..._material_transferred_for_manufacturing.py | 10 - ...ial_transferred_for_manufacturing_again.py | 19 -- .../v5_0/update_operation_description.py | 11 - erpnext/patches/v5_0/update_opportunity.py | 14 - erpnext/patches/v5_0/update_projects.py | 34 --- erpnext/patches/v5_0/update_sms_sender.py | 9 - ...amount_after_discount_in_purchase_cycle.py | 17 -- .../patches/v5_0/update_temporary_account.py | 9 - erpnext/patches/v5_0/update_time_log_title.py | 12 - erpnext/patches/v5_1/__init__.py | 0 erpnext/patches/v5_1/default_bom.py | 7 - erpnext/patches/v5_1/fix_against_account.py | 37 --- erpnext/patches/v5_1/rename_roles.py | 10 - erpnext/patches/v5_1/sales_bom_rename.py | 12 - erpnext/patches/v5_2/__init__.py | 1 - .../v5_2/change_item_selects_to_checks.py | 19 -- erpnext/patches/v5_4/__init__.py | 0 erpnext/patches/v5_4/cleanup_journal_entry.py | 21 -- .../patches/v5_4/fix_invoice_outstanding.py | 13 - .../patches/v5_4/fix_missing_item_images.py | 126 --------- ...x_reserved_qty_and_sle_for_packed_items.py | 22 -- ...anagers_regarding_wrong_tax_calculation.py | 41 --- .../patches/v5_4/set_root_and_report_type.py | 12 - .../v5_4/stock_entry_additional_costs.py | 53 ---- .../update_purchase_cost_against_project.py | 13 - erpnext/patches/v5_7/__init__.py | 1 - .../patches/v5_7/item_template_attributes.py | 124 --------- erpnext/patches/v5_8/__init__.py | 1 - .../v5_8/add_credit_note_print_heading.py | 14 - erpnext/patches/v5_8/tax_rule.py | 31 --- ...pdate_order_reference_in_return_entries.py | 92 ------- erpnext/patches/v6_0/__init__.py | 0 erpnext/patches/v6_0/default_activity_rate.py | 14 - .../patches/v6_0/fix_outstanding_amount.py | 16 -- erpnext/patches/v6_0/fix_planned_qty.py | 14 - erpnext/patches/v6_0/multi_currency.py | 65 ----- erpnext/patches/v6_0/set_default_title.py | 36 --- erpnext/patches/v6_10/__init__.py | 1 - .../v6_10/email_digest_default_quote.py | 6 - .../fix_billed_amount_in_drop_ship_po.py | 18 -- .../fix_delivery_status_of_drop_ship_item.py | 10 - erpnext/patches/v6_10/fix_jv_total_amount.py | 14 - .../v6_10/fix_ordered_received_billed.py | 17 -- erpnext/patches/v6_12/__init__.py | 0 .../repost_entries_with_target_warehouse.py | 175 ------------- erpnext/patches/v6_12/set_overdue_tasks.py | 8 - erpnext/patches/v6_16/__init__.py | 1 - .../v6_16/create_manufacturer_records.py | 19 -- .../update_billing_status_in_dn_and_pr.py | 42 --- erpnext/patches/v6_19/__init__.py | 1 - .../v6_19/comment_feed_communication.py | 7 - erpnext/patches/v6_2/__init__.py | 1 - .../fix_missing_default_taxes_and_lead.py | 25 -- .../v6_2/remove_newsletter_duplicates.py | 13 - erpnext/patches/v6_20/__init__.py | 0 .../set_party_account_currency_in_orders.py | 24 -- erpnext/patches/v6_20x/__init__.py | 1 - .../v6_20x/remove_customer_supplier_roles.py | 23 -- .../remove_fiscal_year_from_holiday_list.py | 19 -- .../v6_20x/rename_project_name_to_project.py | 17 -- ...t_valuation_rate_for_negative_inventory.py | 11 - erpnext/patches/v6_20x/set_compact_print.py | 8 - .../update_product_bundle_description.py | 11 - erpnext/patches/v6_21/__init__.py | 1 - erpnext/patches/v6_21/fix_reorder_level.py | 24 -- .../v6_21/rename_material_request_fields.py | 14 - erpnext/patches/v6_23/__init__.py | 0 .../v6_23/update_stopped_status_to_closed.py | 9 - erpnext/patches/v6_24/__init__.py | 0 ...tomer_address_to_shipping_address_on_po.py | 19 -- erpnext/patches/v6_24/set_recurring_id.py | 13 - erpnext/patches/v6_27/__init__.py | 1 - .../v6_27/fix_recurring_order_status.py | 54 ---- erpnext/patches/v6_3/__init__.py | 0 .../v6_3/convert_applicable_territory.py | 24 -- erpnext/patches/v6_4/__init__.py | 1 - erpnext/patches/v6_4/email_digest_update.py | 10 - erpnext/patches/v6_4/fix_duplicate_bins.py | 20 -- .../v6_4/fix_expense_included_in_valuation.py | 74 ------ ...x_journal_entries_due_to_reconciliation.py | 53 ---- ...ified_in_sales_order_and_purchase_order.py | 10 - .../fix_sales_order_maintenance_status.py | 8 - .../fix_status_in_sales_and_purchase_order.py | 8 - erpnext/patches/v6_4/make_image_thumbnail.py | 15 -- ...al_entries_where_reference_name_missing.py | 23 -- .../v6_4/round_status_updater_percentages.py | 14 - erpnext/patches/v6_4/set_user_in_contact.py | 7 - erpnext/patches/v6_5/__init__.py | 1 - .../v6_5/show_in_website_for_template_item.py | 15 -- erpnext/patches/v6_6/__init__.py | 1 - erpnext/patches/v6_6/fix_website_image.py | 32 --- ...emove_fiscal_year_from_leave_allocation.py | 17 -- erpnext/patches/v6_8/__init__.py | 0 erpnext/patches/v6_8/make_webform_standard.py | 14 - .../v6_8/move_drop_ship_to_po_items.py | 43 ---- erpnext/patches/v7_0/__init__.py | 0 .../v7_0/calculate_total_costing_amount.py | 18 -- .../v7_0/convert_timelog_to_timesheet.py | 69 ----- .../v7_0/convert_timelogbatch_to_timesheet.py | 32 --- erpnext/patches/v7_0/create_budget_record.py | 57 ---- .../v7_0/create_warehouse_nestedset.py | 128 --------- erpnext/patches/v7_0/fix_duplicate_icons.py | 27 -- ...ouse_ledger_gl_entries_for_transactions.py | 51 ---- erpnext/patches/v7_0/make_guardian.py | 37 --- .../v7_0/make_is_group_fieldtype_as_check.py | 18 -- ...count_type_stock_and_warehouse_to_stock.py | 10 - .../v7_0/migrate_mode_of_payments_v6_to_v7.py | 38 --- .../v7_0/migrate_schools_to_erpnext.py | 30 --- ...lesinvoiceitem_to_salesinvoicetimesheet.py | 17 -- .../v7_0/po_status_issue_for_pr_return.py | 40 --- erpnext/patches/v7_0/re_route.py | 5 - .../remove_administrator_role_in_doctypes.py | 9 - .../v7_0/remove_doctypes_and_reports.py | 27 -- erpnext/patches/v7_0/remove_features_setup.py | 29 --- .../remove_old_earning_deduction_doctypes.py | 16 -- .../v7_0/rename_advance_table_fields.py | 18 -- .../v7_0/rename_examination_to_assessment.py | 24 -- .../rename_fee_amount_to_fee_component.py | 16 -- erpnext/patches/v7_0/rename_prevdoc_fields.py | 76 ------ .../patches/v7_0/rename_salary_components.py | 149 ----------- .../patches/v7_0/rename_time_sheet_doctype.py | 14 - .../repost_bin_qty_and_item_projected_qty.py | 15 -- .../repost_gle_for_pi_with_update_stock.py | 20 -- .../v7_0/repost_gle_for_pos_sales_return.py | 25 -- ...et_base_amount_in_invoice_payment_table.py | 24 -- .../v7_0/set_is_group_for_warehouse.py | 7 - .../v7_0/set_material_request_type_in_item.py | 16 -- .../v7_0/set_naming_series_for_timesheet.py | 15 -- .../v7_0/set_party_name_in_payment_entry.py | 20 -- erpnext/patches/v7_0/set_portal_settings.py | 28 -- ..._table_for_expense_claim_type_if_exists.py | 20 -- .../v7_0/system_settings_setup_complete.py | 16 -- erpnext/patches/v7_0/update_autoname_field.py | 14 - .../v7_0/update_change_amount_account.py | 19 -- ...rsion_factor_in_supplier_quotation_item.py | 19 -- erpnext/patches/v7_0/update_home_page.py | 27 -- .../update_maintenance_module_in_doctype.py | 11 - .../v7_0/update_mins_to_first_response.py | 24 -- .../update_missing_employee_in_timesheet.py | 20 -- .../v7_0/update_mode_of_payment_type.py | 29 --- erpnext/patches/v7_0/update_party_status.py | 21 -- ...vdoc_values_for_supplier_quotation_item.py | 9 - .../v7_0/update_project_in_gl_entry.py | 21 -- .../update_refdoc_in_landed_cost_voucher.py | 15 -- .../v7_0/update_status_for_timesheet.py | 11 - .../patches/v7_0/update_status_of_po_so.py | 68 ----- ...pdate_status_of_zero_amount_sales_order.py | 7 - .../v7_0/update_timesheet_communications.py | 27 -- erpnext/patches/v7_1/__init__.py | 1 - .../add_account_user_role_for_timesheet.py | 31 --- .../v7_1/add_field_for_task_dependent.py | 10 - .../v7_1/fix_link_for_customer_from_lead.py | 7 - ..._invoice_from_parent_to_child_timesheet.py | 20 -- .../patches/v7_1/rename_field_timesheet.py | 11 - .../v7_1/rename_quality_inspection_field.py | 38 --- ...tock_for_deleted_bins_for_merging_items.py | 44 ---- erpnext/patches/v7_1/save_stock_settings.py | 15 -- .../v7_1/set_budget_against_as_cost_center.py | 11 - .../v7_1/set_currency_exchange_date.py | 10 - .../v7_1/set_prefered_contact_email.py | 17 -- .../patches/v7_1/set_sales_person_status.py | 8 - erpnext/patches/v7_1/set_student_guardian.py | 23 -- .../v7_1/set_total_amount_currency_in_je.py | 24 -- .../patches/v7_1/update_bom_base_currency.py | 20 -- erpnext/patches/v7_1/update_component_type.py | 15 -- erpnext/patches/v7_1/update_invoice_status.py | 34 --- erpnext/patches/v7_1/update_lead_source.py | 29 --- .../update_missing_salary_component_type.py | 50 ---- erpnext/patches/v7_1/update_portal_roles.py | 21 -- .../v7_1/update_total_billing_hours.py | 14 - erpnext/patches/v7_2/__init__.py | 1 - ...ar_leave_encashment_as_salary_component.py | 36 --- erpnext/patches/v7_2/contact_address_links.py | 32 --- .../delete_fleet_management_module_def.py | 10 - ...ty_supplied_items_for_non_subcontracted.py | 14 - .../patches/v7_2/make_all_assessment_group.py | 14 - erpnext/patches/v7_2/mark_students_active.py | 9 - .../v7_2/rename_att_date_attendance.py | 15 -- .../v7_2/rename_evaluation_criteria.py | 39 --- .../patches/v7_2/set_null_value_to_fields.py | 11 - .../patches/v7_2/setup_auto_close_settings.py | 18 -- erpnext/patches/v7_2/stock_uom_in_selling.py | 15 -- .../v7_2/update_abbr_in_salary_slips.py | 14 - .../patches/v7_2/update_assessment_modules.py | 51 ---- .../v7_2/update_attendance_docstatus.py | 10 - erpnext/patches/v7_2/update_doctype_status.py | 11 - .../update_guardian_name_in_student_master.py | 14 - erpnext/patches/v7_2/update_party_type.py | 16 -- erpnext/patches/v7_2/update_salary_slips.py | 22 -- .../v7_2/update_website_for_variant.py | 13 - erpnext/patches/v8_0/__init__.py | 1 - .../patches/v8_0/addresses_linked_to_lead.py | 5 - .../v8_0/change_in_words_varchar_length.py | 16 -- ...dress_doc_from_address_field_in_company.py | 33 --- erpnext/patches/v8_0/create_domain_docs.py | 53 ---- erpnext/patches/v8_0/delete_bin_indexes.py | 16 -- .../delete_schools_depricated_doctypes.py | 14 - .../patches/v8_0/disable_instructor_role.py | 18 -- ...ooking_asset_depreciation_automatically.py | 9 - ..._for_invoices_with_negative_outstanding.py | 23 -- ...ayments_table_blank_for_non_pos_invoice.py | 15 -- .../merge_student_batch_and_student_group.py | 73 ------ ...from_account_to_warehouse_for_inventory.py | 15 -- .../v8_0/move_perpetual_inventory_setting.py | 13 - ...ample_item_to_allow_zero_valuation_rate.py | 13 - ...ems_in_status_field_of_material_request.py | 25 -- ...rename_total_margin_to_rate_with_margin.py | 24 -- ...ost_reserved_qty_for_multiple_sales_uom.py | 19 -- .../revert_manufacturers_table_from_item.py | 22 -- erpnext/patches/v8_0/save_system_settings.py | 20 -- ..._serial_nos_for_disabled_sales_invoices.py | 14 - .../patches/v8_0/set_project_copied_from.py | 11 - ...nvoice_serial_number_from_delivery_note.py | 42 --- .../patches/v8_0/update_customer_pos_id.py | 9 - .../patches/v8_0/update_production_orders.py | 49 ---- .../v8_0/update_sales_cost_in_project.py | 11 - ...tus_as_paid_for_completed_expense_claim.py | 19 -- .../update_stock_qty_value_in_bom_item.py | 14 - ...ate_stock_qty_value_in_purchase_invoice.py | 9 - ...ate_student_groups_from_student_batches.py | 38 --- .../update_supplier_address_in_stock_entry.py | 22 -- erpnext/patches/v8_1/__init__.py | 0 erpnext/patches/v8_1/add_hsn_sac_codes.py | 11 - .../add_indexes_in_transaction_doctypes.py | 10 - ...allow_invoice_copy_to_edit_after_submit.py | 13 - .../patches/v8_1/delete_deprecated_reports.py | 33 --- erpnext/patches/v8_1/gst_fixes.py | 62 ----- ...e_sales_invoice_from_returned_serial_no.py | 18 -- .../v8_1/removed_report_support_hours.py | 14 - .../v8_1/set_delivery_date_in_so_item.py | 22 -- .../v8_1/update_expense_claim_status.py | 23 -- erpnext/patches/v8_1/update_gst_state.py | 15 -- erpnext/patches/v8_10/__init__.py | 0 .../change_default_customer_credit_days.py | 89 ------- erpnext/patches/v8_3/__init__.py | 0 .../set_restrict_to_domain_for_module_def.py | 9 - .../v8_3/update_company_total_sales.py | 15 -- erpnext/patches/v8_4/__init__.py | 1 - .../patches/v8_4/make_scorecard_records.py | 11 - erpnext/patches/v8_5/__init__.py | 0 .../fix_tax_breakup_for_non_invoice_docs.py | 48 ---- .../remove_project_type_property_setter.py | 18 -- .../remove_quotations_route_in_sidebar.py | 16 -- .../v8_5/set_default_mode_of_payment.py | 17 -- .../update_customer_group_in_POS_profile.py | 9 - .../update_existing_data_in_project_type.py | 19 -- erpnext/patches/v8_6/__init__.py | 0 ...point_sms_doctype_module_to_frappe_core.py | 9 - .../patches/v8_6/rename_bom_update_tool.py | 9 - ...mission_for_quotation_for_sales_manager.py | 11 - .../v8_6/update_timesheet_company_from_PO.py | 15 -- erpnext/patches/v8_7/__init__.py | 0 .../v8_7/fix_purchase_receipt_status.py | 13 - .../make_subscription_from_recurring_data.py | 58 ----- erpnext/patches/v8_8/__init__.py | 0 .../add_new_fields_in_accounts_settings.py | 9 - .../patches/v8_8/set_bom_rate_as_per_uom.py | 13 - erpnext/patches/v8_9/__init__.py | 1 - .../v8_9/add_setup_progress_actions.py | 47 ---- ...gst_doctypes_for_outside_india_accounts.py | 14 - ...e_employee_from_salary_structure_parent.py | 6 - .../v8_9/rename_company_sales_target_field.py | 8 - .../v8_9/set_default_customer_group.py | 8 - .../set_default_fields_in_variant_settings.py | 13 - erpnext/patches/v8_9/set_member_party_type.py | 9 - .../v8_9/set_print_zero_amount_taxes.py | 9 - ...update_billing_gstin_for_indian_account.py | 15 -- erpnext/patches/v9_0/__init__.py | 1 - erpnext/patches/v9_0/add_healthcare_domain.py | 13 - .../add_user_to_child_table_in_pos_profile.py | 38 --- .../patches/v9_0/copy_old_fees_field_data.py | 15 -- ..._existing_warehouse_from_stock_settings.py | 8 - .../v9_0/remove_subscription_module.py | 9 - .../v9_0/revert_manufacturing_user_role.py | 22 -- erpnext/patches/v9_0/set_pos_profile_name.py | 24 -- ...for_material_request_and_purchase_order.py | 24 -- ...ipping_type_for_existing_shipping_rules.py | 18 -- .../patches/v9_0/set_uoms_in_variant_field.py | 14 - .../v9_0/set_variant_item_description.py | 46 ---- .../student_admission_childtable_migrate.py | 31 --- .../v9_0/update_employee_loan_details.py | 24 -- ...te_multi_uom_fields_in_material_request.py | 12 - erpnext/patches/v9_1/__init__.py | 0 .../v9_1/create_issue_opportunity_type.py | 34 --- erpnext/patches/v9_2/__init__.py | 0 .../delete_healthcare_domain_default_items.py | 17 -- .../patches/v9_2/delete_process_payroll.py | 5 - .../v9_2/remove_company_from_patient.py | 7 - .../v9_2/rename_net_weight_in_item_master.py | 8 - .../v9_2/rename_translated_domains_in_en.py | 39 --- .../repost_reserved_qty_for_production.py | 9 - .../v9_2/set_item_name_in_production_order.py | 12 - 441 files changed, 9599 deletions(-) delete mode 100644 erpnext/patches/repair_tools/__init__.py delete mode 100644 erpnext/patches/repair_tools/set_stock_balance_as_per_serial_no.py delete mode 100644 erpnext/patches/v10_0/__init__.py delete mode 100644 erpnext/patches/v10_0/add_agriculture_domain.py delete mode 100644 erpnext/patches/v10_0/add_guardian_role_for_parent_portal.py delete mode 100644 erpnext/patches/v10_0/add_non_profit_domain.py delete mode 100644 erpnext/patches/v10_0/allow_operators_in_supplier_scorecard.py delete mode 100644 erpnext/patches/v10_0/copy_projects_renamed_fields.py delete mode 100644 erpnext/patches/v10_0/enabled_regional_print_format_based_on_country.py delete mode 100644 erpnext/patches/v10_0/fix_reserved_qty_for_sub_contract.py delete mode 100644 erpnext/patches/v10_0/recalculate_gross_margin_for_project.py delete mode 100644 erpnext/patches/v10_0/rename_schools_to_education.py delete mode 100644 erpnext/patches/v10_0/repost_gle_for_purchase_receipts_with_rejected_items.py delete mode 100644 erpnext/patches/v10_0/repost_requested_qty_for_non_stock_uom_items.py delete mode 100644 erpnext/patches/v10_0/set_auto_created_serial_no_in_stock_entry.py delete mode 100644 erpnext/patches/v10_0/set_b2c_limit.py delete mode 100644 erpnext/patches/v10_0/set_default_payment_terms_based_on_company.py delete mode 100644 erpnext/patches/v10_0/set_discount_amount.py delete mode 100644 erpnext/patches/v10_0/set_numeric_ranges_in_template_if_blank.py delete mode 100644 erpnext/patches/v10_0/set_primary_contact_for_customer.py delete mode 100644 erpnext/patches/v10_0/set_qty_in_transactions_based_on_serial_no_input.py delete mode 100644 erpnext/patches/v10_0/set_student_party_type.py delete mode 100644 erpnext/patches/v10_0/setup_vat_for_uae_and_saudi_arabia.py delete mode 100644 erpnext/patches/v10_0/show_leaves_of_all_department_members_in_calendar.py delete mode 100644 erpnext/patches/v10_0/taxes_issue_with_pos.py delete mode 100644 erpnext/patches/v10_0/update_address_template_for_india.py delete mode 100644 erpnext/patches/v10_0/update_assessment_plan.py delete mode 100644 erpnext/patches/v10_0/update_assessment_result.py delete mode 100644 erpnext/patches/v10_0/update_asset_calculate_depreciation.py delete mode 100644 erpnext/patches/v10_0/update_hub_connector_domain.py delete mode 100644 erpnext/patches/v10_0/update_lft_rgt_for_employee.py delete mode 100644 erpnext/patches/v10_0/update_project_in_sle.py delete mode 100644 erpnext/patches/v10_0/update_reserved_qty_for_purchase_order.py delete mode 100644 erpnext/patches/v10_0/update_sales_order_link_to_purchase_order.py delete mode 100644 erpnext/patches/v10_0/update_status_for_multiple_source_in_po.py delete mode 100644 erpnext/patches/v10_0/update_status_in_purchase_receipt.py delete mode 100644 erpnext/patches/v10_0/update_territory_and_customer_group.py delete mode 100644 erpnext/patches/v10_0/update_user_image_in_employee.py delete mode 100644 erpnext/patches/v10_0/update_warehouse_address_details.py delete mode 100644 erpnext/patches/v10_1/__init__.py delete mode 100644 erpnext/patches/v11_0/__init__.py delete mode 100644 erpnext/patches/v11_0/remove_subscriber_doctype.py delete mode 100644 erpnext/patches/v11_1/__init__.py delete mode 100644 erpnext/patches/v12_0/__init__.py delete mode 100644 erpnext/patches/v13_0/__init__.py delete mode 100644 erpnext/patches/v4_0/__init__.py delete mode 100644 erpnext/patches/v4_0/apply_user_permissions.py delete mode 100644 erpnext/patches/v4_0/countrywise_coa.py delete mode 100644 erpnext/patches/v4_0/create_custom_fields_for_india_specific_fields.py delete mode 100644 erpnext/patches/v4_0/create_price_list_if_missing.py delete mode 100644 erpnext/patches/v4_0/customer_discount_to_pricing_rule.py delete mode 100644 erpnext/patches/v4_0/fields_to_be_renamed.py delete mode 100644 erpnext/patches/v4_0/fix_address_template.py delete mode 100644 erpnext/patches/v4_0/fix_case_of_hr_module_def.py delete mode 100644 erpnext/patches/v4_0/fix_contact_address.py delete mode 100644 erpnext/patches/v4_0/fix_employee_user_id.py delete mode 100644 erpnext/patches/v4_0/global_defaults_to_system_settings.py delete mode 100644 erpnext/patches/v4_0/import_country_codes.py delete mode 100644 erpnext/patches/v4_0/map_charge_to_taxes_and_charges.py delete mode 100644 erpnext/patches/v4_0/move_warehouse_user_to_restrictions.py delete mode 100644 erpnext/patches/v4_0/new_address_template.py delete mode 100644 erpnext/patches/v4_0/reload_sales_print_format.py delete mode 100644 erpnext/patches/v4_0/remove_employee_role_if_no_employee.py delete mode 100644 erpnext/patches/v4_0/remove_module_home_pages.py delete mode 100644 erpnext/patches/v4_0/rename_sitemap_to_route.py delete mode 100644 erpnext/patches/v4_0/reset_permissions_for_masters.py delete mode 100644 erpnext/patches/v4_0/save_default_letterhead.py delete mode 100644 erpnext/patches/v4_0/set_pricing_rule_for_buying_or_selling.py delete mode 100644 erpnext/patches/v4_0/split_email_settings.py delete mode 100644 erpnext/patches/v4_0/update_account_root_type.py delete mode 100644 erpnext/patches/v4_0/update_custom_print_formats_for_renamed_fields.py delete mode 100644 erpnext/patches/v4_0/update_incharge_name_to_sales_person_in_maintenance_schedule.py delete mode 100644 erpnext/patches/v4_0/update_other_charges_in_custom_purchase_print_formats.py delete mode 100644 erpnext/patches/v4_0/update_tax_amount_after_discount.py delete mode 100644 erpnext/patches/v4_0/update_user_properties.py delete mode 100644 erpnext/patches/v4_0/update_users_report_view_settings.py delete mode 100644 erpnext/patches/v4_0/validate_v3_patch.py delete mode 100644 erpnext/patches/v4_1/__init__.py delete mode 100644 erpnext/patches/v4_1/fix_delivery_and_billing_status.py delete mode 100644 erpnext/patches/v4_1/fix_jv_remarks.py delete mode 100644 erpnext/patches/v4_1/fix_sales_order_delivered_status.py delete mode 100644 erpnext/patches/v4_1/set_outgoing_email_footer.py delete mode 100644 erpnext/patches/v4_2/__init__.py delete mode 100644 erpnext/patches/v4_2/add_currency_turkish_lira.py delete mode 100644 erpnext/patches/v4_2/default_website_style.py delete mode 100644 erpnext/patches/v4_2/delete_gl_entries_for_cancelled_invoices.py delete mode 100644 erpnext/patches/v4_2/delete_old_print_formats.py delete mode 100644 erpnext/patches/v4_2/discount_amount.py delete mode 100644 erpnext/patches/v4_2/fix_account_master_type.py delete mode 100644 erpnext/patches/v4_2/fix_gl_entries_for_stock_transactions.py delete mode 100644 erpnext/patches/v4_2/fix_recurring_orders.py delete mode 100644 erpnext/patches/v4_2/party_model.py delete mode 100644 erpnext/patches/v4_2/recalculate_bom_cost.py delete mode 100644 erpnext/patches/v4_2/repost_sle_for_si_with_no_warehouse.py delete mode 100644 erpnext/patches/v4_2/repost_stock_reconciliation.py delete mode 100644 erpnext/patches/v4_2/reset_bom_costs.py delete mode 100644 erpnext/patches/v4_2/seprate_manufacture_and_repack.py delete mode 100644 erpnext/patches/v4_2/set_company_country.py delete mode 100644 erpnext/patches/v4_2/set_item_has_batch.py delete mode 100644 erpnext/patches/v4_2/toggle_rounded_total.py delete mode 100644 erpnext/patches/v4_2/update_landed_cost_voucher.py delete mode 100644 erpnext/patches/v4_2/update_project_milestones.py delete mode 100644 erpnext/patches/v4_2/update_sales_order_invoice_field_name.py delete mode 100644 erpnext/patches/v4_2/update_stock_uom_for_dn_in_sle.py delete mode 100644 erpnext/patches/v4_4/__init__.py delete mode 100644 erpnext/patches/v4_4/make_email_accounts.py delete mode 100644 erpnext/patches/v5_0/__init__.py delete mode 100644 erpnext/patches/v5_0/convert_stock_reconciliation.py delete mode 100644 erpnext/patches/v5_0/execute_on_doctype_update.py delete mode 100644 erpnext/patches/v5_0/fix_taxes_and_totals_in_party_currency.py delete mode 100644 erpnext/patches/v5_0/index_on_account_and_gl_entry.py delete mode 100644 erpnext/patches/v5_0/is_group.py delete mode 100644 erpnext/patches/v5_0/item_patches.py delete mode 100644 erpnext/patches/v5_0/link_warehouse_with_account.py delete mode 100644 erpnext/patches/v5_0/new_crm_module.py delete mode 100644 erpnext/patches/v5_0/newsletter.py delete mode 100644 erpnext/patches/v5_0/opportunity_not_submittable.py delete mode 100644 erpnext/patches/v5_0/party_model_patch_fix.py delete mode 100644 erpnext/patches/v5_0/portal_fixes.py delete mode 100644 erpnext/patches/v5_0/project_costing.py delete mode 100644 erpnext/patches/v5_0/recalculate_total_amount_in_jv.py delete mode 100644 erpnext/patches/v5_0/reclculate_planned_operating_cost_in_production_order.py delete mode 100644 erpnext/patches/v5_0/remove_birthday_events.py delete mode 100644 erpnext/patches/v5_0/rename_customer_issue.py delete mode 100644 erpnext/patches/v5_0/rename_pos_setting.py delete mode 100644 erpnext/patches/v5_0/rename_table_fieldnames.py delete mode 100644 erpnext/patches/v5_0/rename_taxes_and_charges_master.py delete mode 100644 erpnext/patches/v5_0/rename_total_fields.py delete mode 100644 erpnext/patches/v5_0/replace_renamed_fields_in_custom_scripts_and_print_formats.py delete mode 100644 erpnext/patches/v5_0/repost_gle_for_jv_with_multiple_party.py delete mode 100644 erpnext/patches/v5_0/repost_requested_qty.py delete mode 100644 erpnext/patches/v5_0/reset_values_in_tools.py delete mode 100644 erpnext/patches/v5_0/set_appraisal_remarks.py delete mode 100644 erpnext/patches/v5_0/set_default_company_in_bom.py delete mode 100644 erpnext/patches/v5_0/set_footer_address.py delete mode 100644 erpnext/patches/v5_0/stock_entry_update_value.py delete mode 100644 erpnext/patches/v5_0/taxes_and_totals_in_party_currency.py delete mode 100644 erpnext/patches/v5_0/update_account_types.py delete mode 100644 erpnext/patches/v5_0/update_advance_paid.py delete mode 100644 erpnext/patches/v5_0/update_companywise_payment_account.py delete mode 100644 erpnext/patches/v5_0/update_dn_against_doc_fields.py delete mode 100644 erpnext/patches/v5_0/update_from_bom.py delete mode 100644 erpnext/patches/v5_0/update_frozen_accounts_permission_role.py delete mode 100644 erpnext/patches/v5_0/update_item_and_description_again.py delete mode 100644 erpnext/patches/v5_0/update_item_desc_in_invoice.py delete mode 100644 erpnext/patches/v5_0/update_item_description_and_image.py delete mode 100644 erpnext/patches/v5_0/update_item_name_in_bom.py delete mode 100644 erpnext/patches/v5_0/update_journal_entry_title.py delete mode 100644 erpnext/patches/v5_0/update_material_transfer_for_manufacture.py delete mode 100644 erpnext/patches/v5_0/update_material_transferred_for_manufacturing.py delete mode 100644 erpnext/patches/v5_0/update_material_transferred_for_manufacturing_again.py delete mode 100644 erpnext/patches/v5_0/update_operation_description.py delete mode 100644 erpnext/patches/v5_0/update_opportunity.py delete mode 100644 erpnext/patches/v5_0/update_projects.py delete mode 100644 erpnext/patches/v5_0/update_sms_sender.py delete mode 100644 erpnext/patches/v5_0/update_tax_amount_after_discount_in_purchase_cycle.py delete mode 100644 erpnext/patches/v5_0/update_temporary_account.py delete mode 100644 erpnext/patches/v5_0/update_time_log_title.py delete mode 100644 erpnext/patches/v5_1/__init__.py delete mode 100644 erpnext/patches/v5_1/default_bom.py delete mode 100644 erpnext/patches/v5_1/fix_against_account.py delete mode 100644 erpnext/patches/v5_1/rename_roles.py delete mode 100644 erpnext/patches/v5_1/sales_bom_rename.py delete mode 100644 erpnext/patches/v5_2/__init__.py delete mode 100644 erpnext/patches/v5_2/change_item_selects_to_checks.py delete mode 100644 erpnext/patches/v5_4/__init__.py delete mode 100644 erpnext/patches/v5_4/cleanup_journal_entry.py delete mode 100644 erpnext/patches/v5_4/fix_invoice_outstanding.py delete mode 100644 erpnext/patches/v5_4/fix_missing_item_images.py delete mode 100644 erpnext/patches/v5_4/fix_reserved_qty_and_sle_for_packed_items.py delete mode 100644 erpnext/patches/v5_4/notify_system_managers_regarding_wrong_tax_calculation.py delete mode 100644 erpnext/patches/v5_4/set_root_and_report_type.py delete mode 100644 erpnext/patches/v5_4/stock_entry_additional_costs.py delete mode 100644 erpnext/patches/v5_4/update_purchase_cost_against_project.py delete mode 100644 erpnext/patches/v5_7/__init__.py delete mode 100644 erpnext/patches/v5_7/item_template_attributes.py delete mode 100644 erpnext/patches/v5_8/__init__.py delete mode 100644 erpnext/patches/v5_8/add_credit_note_print_heading.py delete mode 100644 erpnext/patches/v5_8/tax_rule.py delete mode 100644 erpnext/patches/v5_8/update_order_reference_in_return_entries.py delete mode 100644 erpnext/patches/v6_0/__init__.py delete mode 100644 erpnext/patches/v6_0/default_activity_rate.py delete mode 100644 erpnext/patches/v6_0/fix_outstanding_amount.py delete mode 100644 erpnext/patches/v6_0/fix_planned_qty.py delete mode 100644 erpnext/patches/v6_0/multi_currency.py delete mode 100644 erpnext/patches/v6_0/set_default_title.py delete mode 100644 erpnext/patches/v6_10/__init__.py delete mode 100644 erpnext/patches/v6_10/email_digest_default_quote.py delete mode 100644 erpnext/patches/v6_10/fix_billed_amount_in_drop_ship_po.py delete mode 100644 erpnext/patches/v6_10/fix_delivery_status_of_drop_ship_item.py delete mode 100644 erpnext/patches/v6_10/fix_jv_total_amount.py delete mode 100644 erpnext/patches/v6_10/fix_ordered_received_billed.py delete mode 100644 erpnext/patches/v6_12/__init__.py delete mode 100644 erpnext/patches/v6_12/repost_entries_with_target_warehouse.py delete mode 100644 erpnext/patches/v6_12/set_overdue_tasks.py delete mode 100644 erpnext/patches/v6_16/__init__.py delete mode 100644 erpnext/patches/v6_16/create_manufacturer_records.py delete mode 100644 erpnext/patches/v6_16/update_billing_status_in_dn_and_pr.py delete mode 100644 erpnext/patches/v6_19/__init__.py delete mode 100644 erpnext/patches/v6_19/comment_feed_communication.py delete mode 100644 erpnext/patches/v6_2/__init__.py delete mode 100644 erpnext/patches/v6_2/fix_missing_default_taxes_and_lead.py delete mode 100644 erpnext/patches/v6_2/remove_newsletter_duplicates.py delete mode 100644 erpnext/patches/v6_20/__init__.py delete mode 100644 erpnext/patches/v6_20/set_party_account_currency_in_orders.py delete mode 100644 erpnext/patches/v6_20x/__init__.py delete mode 100644 erpnext/patches/v6_20x/remove_customer_supplier_roles.py delete mode 100644 erpnext/patches/v6_20x/remove_fiscal_year_from_holiday_list.py delete mode 100644 erpnext/patches/v6_20x/rename_project_name_to_project.py delete mode 100644 erpnext/patches/v6_20x/repost_valuation_rate_for_negative_inventory.py delete mode 100644 erpnext/patches/v6_20x/set_compact_print.py delete mode 100644 erpnext/patches/v6_20x/update_product_bundle_description.py delete mode 100644 erpnext/patches/v6_21/__init__.py delete mode 100644 erpnext/patches/v6_21/fix_reorder_level.py delete mode 100644 erpnext/patches/v6_21/rename_material_request_fields.py delete mode 100644 erpnext/patches/v6_23/__init__.py delete mode 100644 erpnext/patches/v6_23/update_stopped_status_to_closed.py delete mode 100644 erpnext/patches/v6_24/__init__.py delete mode 100644 erpnext/patches/v6_24/map_customer_address_to_shipping_address_on_po.py delete mode 100644 erpnext/patches/v6_24/set_recurring_id.py delete mode 100644 erpnext/patches/v6_27/__init__.py delete mode 100644 erpnext/patches/v6_27/fix_recurring_order_status.py delete mode 100644 erpnext/patches/v6_3/__init__.py delete mode 100644 erpnext/patches/v6_3/convert_applicable_territory.py delete mode 100644 erpnext/patches/v6_4/__init__.py delete mode 100644 erpnext/patches/v6_4/email_digest_update.py delete mode 100644 erpnext/patches/v6_4/fix_duplicate_bins.py delete mode 100644 erpnext/patches/v6_4/fix_expense_included_in_valuation.py delete mode 100644 erpnext/patches/v6_4/fix_journal_entries_due_to_reconciliation.py delete mode 100644 erpnext/patches/v6_4/fix_modified_in_sales_order_and_purchase_order.py delete mode 100644 erpnext/patches/v6_4/fix_sales_order_maintenance_status.py delete mode 100644 erpnext/patches/v6_4/fix_status_in_sales_and_purchase_order.py delete mode 100644 erpnext/patches/v6_4/make_image_thumbnail.py delete mode 100644 erpnext/patches/v6_4/repost_gle_for_journal_entries_where_reference_name_missing.py delete mode 100644 erpnext/patches/v6_4/round_status_updater_percentages.py delete mode 100644 erpnext/patches/v6_4/set_user_in_contact.py delete mode 100644 erpnext/patches/v6_5/__init__.py delete mode 100644 erpnext/patches/v6_5/show_in_website_for_template_item.py delete mode 100644 erpnext/patches/v6_6/__init__.py delete mode 100644 erpnext/patches/v6_6/fix_website_image.py delete mode 100644 erpnext/patches/v6_6/remove_fiscal_year_from_leave_allocation.py delete mode 100644 erpnext/patches/v6_8/__init__.py delete mode 100644 erpnext/patches/v6_8/make_webform_standard.py delete mode 100644 erpnext/patches/v6_8/move_drop_ship_to_po_items.py delete mode 100644 erpnext/patches/v7_0/__init__.py delete mode 100644 erpnext/patches/v7_0/calculate_total_costing_amount.py delete mode 100644 erpnext/patches/v7_0/convert_timelog_to_timesheet.py delete mode 100644 erpnext/patches/v7_0/convert_timelogbatch_to_timesheet.py delete mode 100644 erpnext/patches/v7_0/create_budget_record.py delete mode 100644 erpnext/patches/v7_0/create_warehouse_nestedset.py delete mode 100644 erpnext/patches/v7_0/fix_duplicate_icons.py delete mode 100644 erpnext/patches/v7_0/fix_nonwarehouse_ledger_gl_entries_for_transactions.py delete mode 100644 erpnext/patches/v7_0/make_guardian.py delete mode 100644 erpnext/patches/v7_0/make_is_group_fieldtype_as_check.py delete mode 100644 erpnext/patches/v7_0/merge_account_type_stock_and_warehouse_to_stock.py delete mode 100644 erpnext/patches/v7_0/migrate_mode_of_payments_v6_to_v7.py delete mode 100644 erpnext/patches/v7_0/migrate_schools_to_erpnext.py delete mode 100644 erpnext/patches/v7_0/move_timelogbatch_from_salesinvoiceitem_to_salesinvoicetimesheet.py delete mode 100644 erpnext/patches/v7_0/po_status_issue_for_pr_return.py delete mode 100644 erpnext/patches/v7_0/re_route.py delete mode 100644 erpnext/patches/v7_0/remove_administrator_role_in_doctypes.py delete mode 100644 erpnext/patches/v7_0/remove_doctypes_and_reports.py delete mode 100644 erpnext/patches/v7_0/remove_features_setup.py delete mode 100644 erpnext/patches/v7_0/remove_old_earning_deduction_doctypes.py delete mode 100644 erpnext/patches/v7_0/rename_advance_table_fields.py delete mode 100644 erpnext/patches/v7_0/rename_examination_to_assessment.py delete mode 100644 erpnext/patches/v7_0/rename_fee_amount_to_fee_component.py delete mode 100644 erpnext/patches/v7_0/rename_prevdoc_fields.py delete mode 100644 erpnext/patches/v7_0/rename_salary_components.py delete mode 100644 erpnext/patches/v7_0/rename_time_sheet_doctype.py delete mode 100644 erpnext/patches/v7_0/repost_bin_qty_and_item_projected_qty.py delete mode 100644 erpnext/patches/v7_0/repost_gle_for_pi_with_update_stock.py delete mode 100644 erpnext/patches/v7_0/repost_gle_for_pos_sales_return.py delete mode 100644 erpnext/patches/v7_0/set_base_amount_in_invoice_payment_table.py delete mode 100644 erpnext/patches/v7_0/set_is_group_for_warehouse.py delete mode 100644 erpnext/patches/v7_0/set_material_request_type_in_item.py delete mode 100644 erpnext/patches/v7_0/set_naming_series_for_timesheet.py delete mode 100644 erpnext/patches/v7_0/set_party_name_in_payment_entry.py delete mode 100644 erpnext/patches/v7_0/set_portal_settings.py delete mode 100644 erpnext/patches/v7_0/setup_account_table_for_expense_claim_type_if_exists.py delete mode 100644 erpnext/patches/v7_0/system_settings_setup_complete.py delete mode 100644 erpnext/patches/v7_0/update_autoname_field.py delete mode 100644 erpnext/patches/v7_0/update_change_amount_account.py delete mode 100644 erpnext/patches/v7_0/update_conversion_factor_in_supplier_quotation_item.py delete mode 100644 erpnext/patches/v7_0/update_home_page.py delete mode 100644 erpnext/patches/v7_0/update_maintenance_module_in_doctype.py delete mode 100644 erpnext/patches/v7_0/update_mins_to_first_response.py delete mode 100644 erpnext/patches/v7_0/update_missing_employee_in_timesheet.py delete mode 100644 erpnext/patches/v7_0/update_mode_of_payment_type.py delete mode 100644 erpnext/patches/v7_0/update_party_status.py delete mode 100644 erpnext/patches/v7_0/update_prevdoc_values_for_supplier_quotation_item.py delete mode 100644 erpnext/patches/v7_0/update_project_in_gl_entry.py delete mode 100644 erpnext/patches/v7_0/update_refdoc_in_landed_cost_voucher.py delete mode 100644 erpnext/patches/v7_0/update_status_for_timesheet.py delete mode 100644 erpnext/patches/v7_0/update_status_of_po_so.py delete mode 100644 erpnext/patches/v7_0/update_status_of_zero_amount_sales_order.py delete mode 100644 erpnext/patches/v7_0/update_timesheet_communications.py delete mode 100644 erpnext/patches/v7_1/__init__.py delete mode 100644 erpnext/patches/v7_1/add_account_user_role_for_timesheet.py delete mode 100644 erpnext/patches/v7_1/add_field_for_task_dependent.py delete mode 100644 erpnext/patches/v7_1/fix_link_for_customer_from_lead.py delete mode 100644 erpnext/patches/v7_1/move_sales_invoice_from_parent_to_child_timesheet.py delete mode 100644 erpnext/patches/v7_1/rename_field_timesheet.py delete mode 100644 erpnext/patches/v7_1/rename_quality_inspection_field.py delete mode 100644 erpnext/patches/v7_1/repost_stock_for_deleted_bins_for_merging_items.py delete mode 100644 erpnext/patches/v7_1/save_stock_settings.py delete mode 100644 erpnext/patches/v7_1/set_budget_against_as_cost_center.py delete mode 100644 erpnext/patches/v7_1/set_currency_exchange_date.py delete mode 100644 erpnext/patches/v7_1/set_prefered_contact_email.py delete mode 100644 erpnext/patches/v7_1/set_sales_person_status.py delete mode 100644 erpnext/patches/v7_1/set_student_guardian.py delete mode 100644 erpnext/patches/v7_1/set_total_amount_currency_in_je.py delete mode 100644 erpnext/patches/v7_1/update_bom_base_currency.py delete mode 100644 erpnext/patches/v7_1/update_component_type.py delete mode 100644 erpnext/patches/v7_1/update_invoice_status.py delete mode 100644 erpnext/patches/v7_1/update_lead_source.py delete mode 100644 erpnext/patches/v7_1/update_missing_salary_component_type.py delete mode 100644 erpnext/patches/v7_1/update_portal_roles.py delete mode 100644 erpnext/patches/v7_1/update_total_billing_hours.py delete mode 100644 erpnext/patches/v7_2/__init__.py delete mode 100644 erpnext/patches/v7_2/arrear_leave_encashment_as_salary_component.py delete mode 100644 erpnext/patches/v7_2/contact_address_links.py delete mode 100644 erpnext/patches/v7_2/delete_fleet_management_module_def.py delete mode 100644 erpnext/patches/v7_2/empty_supplied_items_for_non_subcontracted.py delete mode 100644 erpnext/patches/v7_2/make_all_assessment_group.py delete mode 100644 erpnext/patches/v7_2/mark_students_active.py delete mode 100644 erpnext/patches/v7_2/rename_att_date_attendance.py delete mode 100644 erpnext/patches/v7_2/rename_evaluation_criteria.py delete mode 100644 erpnext/patches/v7_2/set_null_value_to_fields.py delete mode 100644 erpnext/patches/v7_2/setup_auto_close_settings.py delete mode 100644 erpnext/patches/v7_2/stock_uom_in_selling.py delete mode 100644 erpnext/patches/v7_2/update_abbr_in_salary_slips.py delete mode 100644 erpnext/patches/v7_2/update_assessment_modules.py delete mode 100644 erpnext/patches/v7_2/update_attendance_docstatus.py delete mode 100644 erpnext/patches/v7_2/update_doctype_status.py delete mode 100644 erpnext/patches/v7_2/update_guardian_name_in_student_master.py delete mode 100644 erpnext/patches/v7_2/update_party_type.py delete mode 100644 erpnext/patches/v7_2/update_salary_slips.py delete mode 100644 erpnext/patches/v7_2/update_website_for_variant.py delete mode 100644 erpnext/patches/v8_0/__init__.py delete mode 100644 erpnext/patches/v8_0/addresses_linked_to_lead.py delete mode 100644 erpnext/patches/v8_0/change_in_words_varchar_length.py delete mode 100644 erpnext/patches/v8_0/create_address_doc_from_address_field_in_company.py delete mode 100644 erpnext/patches/v8_0/create_domain_docs.py delete mode 100644 erpnext/patches/v8_0/delete_bin_indexes.py delete mode 100644 erpnext/patches/v8_0/delete_schools_depricated_doctypes.py delete mode 100644 erpnext/patches/v8_0/disable_instructor_role.py delete mode 100644 erpnext/patches/v8_0/enable_booking_asset_depreciation_automatically.py delete mode 100644 erpnext/patches/v8_0/fix_status_for_invoices_with_negative_outstanding.py delete mode 100644 erpnext/patches/v8_0/make_payments_table_blank_for_non_pos_invoice.py delete mode 100644 erpnext/patches/v8_0/merge_student_batch_and_student_group.py delete mode 100644 erpnext/patches/v8_0/move_account_head_from_account_to_warehouse_for_inventory.py delete mode 100644 erpnext/patches/v8_0/move_perpetual_inventory_setting.py delete mode 100644 erpnext/patches/v8_0/rename_is_sample_item_to_allow_zero_valuation_rate.py delete mode 100644 erpnext/patches/v8_0/rename_items_in_status_field_of_material_request.py delete mode 100644 erpnext/patches/v8_0/rename_total_margin_to_rate_with_margin.py delete mode 100644 erpnext/patches/v8_0/repost_reserved_qty_for_multiple_sales_uom.py delete mode 100644 erpnext/patches/v8_0/revert_manufacturers_table_from_item.py delete mode 100644 erpnext/patches/v8_0/save_system_settings.py delete mode 100644 erpnext/patches/v8_0/set_null_to_serial_nos_for_disabled_sales_invoices.py delete mode 100644 erpnext/patches/v8_0/set_project_copied_from.py delete mode 100644 erpnext/patches/v8_0/set_sales_invoice_serial_number_from_delivery_note.py delete mode 100644 erpnext/patches/v8_0/update_customer_pos_id.py delete mode 100644 erpnext/patches/v8_0/update_production_orders.py delete mode 100644 erpnext/patches/v8_0/update_sales_cost_in_project.py delete mode 100644 erpnext/patches/v8_0/update_status_as_paid_for_completed_expense_claim.py delete mode 100644 erpnext/patches/v8_0/update_stock_qty_value_in_bom_item.py delete mode 100644 erpnext/patches/v8_0/update_stock_qty_value_in_purchase_invoice.py delete mode 100644 erpnext/patches/v8_0/update_student_groups_from_student_batches.py delete mode 100644 erpnext/patches/v8_0/update_supplier_address_in_stock_entry.py delete mode 100644 erpnext/patches/v8_1/__init__.py delete mode 100644 erpnext/patches/v8_1/add_hsn_sac_codes.py delete mode 100644 erpnext/patches/v8_1/add_indexes_in_transaction_doctypes.py delete mode 100644 erpnext/patches/v8_1/allow_invoice_copy_to_edit_after_submit.py delete mode 100644 erpnext/patches/v8_1/delete_deprecated_reports.py delete mode 100644 erpnext/patches/v8_1/gst_fixes.py delete mode 100644 erpnext/patches/v8_1/remove_sales_invoice_from_returned_serial_no.py delete mode 100644 erpnext/patches/v8_1/removed_report_support_hours.py delete mode 100644 erpnext/patches/v8_1/set_delivery_date_in_so_item.py delete mode 100644 erpnext/patches/v8_1/update_expense_claim_status.py delete mode 100644 erpnext/patches/v8_1/update_gst_state.py delete mode 100644 erpnext/patches/v8_10/__init__.py delete mode 100644 erpnext/patches/v8_10/change_default_customer_credit_days.py delete mode 100644 erpnext/patches/v8_3/__init__.py delete mode 100644 erpnext/patches/v8_3/set_restrict_to_domain_for_module_def.py delete mode 100644 erpnext/patches/v8_3/update_company_total_sales.py delete mode 100644 erpnext/patches/v8_4/__init__.py delete mode 100644 erpnext/patches/v8_4/make_scorecard_records.py delete mode 100644 erpnext/patches/v8_5/__init__.py delete mode 100644 erpnext/patches/v8_5/fix_tax_breakup_for_non_invoice_docs.py delete mode 100644 erpnext/patches/v8_5/remove_project_type_property_setter.py delete mode 100644 erpnext/patches/v8_5/remove_quotations_route_in_sidebar.py delete mode 100644 erpnext/patches/v8_5/set_default_mode_of_payment.py delete mode 100644 erpnext/patches/v8_5/update_customer_group_in_POS_profile.py delete mode 100644 erpnext/patches/v8_5/update_existing_data_in_project_type.py delete mode 100644 erpnext/patches/v8_6/__init__.py delete mode 100644 erpnext/patches/v8_6/point_sms_doctype_module_to_frappe_core.py delete mode 100644 erpnext/patches/v8_6/rename_bom_update_tool.py delete mode 100644 erpnext/patches/v8_6/set_write_permission_for_quotation_for_sales_manager.py delete mode 100644 erpnext/patches/v8_6/update_timesheet_company_from_PO.py delete mode 100644 erpnext/patches/v8_7/__init__.py delete mode 100644 erpnext/patches/v8_7/fix_purchase_receipt_status.py delete mode 100644 erpnext/patches/v8_7/make_subscription_from_recurring_data.py delete mode 100644 erpnext/patches/v8_8/__init__.py delete mode 100644 erpnext/patches/v8_8/add_new_fields_in_accounts_settings.py delete mode 100644 erpnext/patches/v8_8/set_bom_rate_as_per_uom.py delete mode 100644 erpnext/patches/v8_9/__init__.py delete mode 100644 erpnext/patches/v8_9/add_setup_progress_actions.py delete mode 100644 erpnext/patches/v8_9/delete_gst_doctypes_for_outside_india_accounts.py delete mode 100644 erpnext/patches/v8_9/remove_employee_from_salary_structure_parent.py delete mode 100644 erpnext/patches/v8_9/rename_company_sales_target_field.py delete mode 100644 erpnext/patches/v8_9/set_default_customer_group.py delete mode 100644 erpnext/patches/v8_9/set_default_fields_in_variant_settings.py delete mode 100644 erpnext/patches/v8_9/set_member_party_type.py delete mode 100644 erpnext/patches/v8_9/set_print_zero_amount_taxes.py delete mode 100644 erpnext/patches/v8_9/update_billing_gstin_for_indian_account.py delete mode 100644 erpnext/patches/v9_0/__init__.py delete mode 100644 erpnext/patches/v9_0/add_healthcare_domain.py delete mode 100644 erpnext/patches/v9_0/add_user_to_child_table_in_pos_profile.py delete mode 100644 erpnext/patches/v9_0/copy_old_fees_field_data.py delete mode 100644 erpnext/patches/v9_0/remove_non_existing_warehouse_from_stock_settings.py delete mode 100644 erpnext/patches/v9_0/remove_subscription_module.py delete mode 100644 erpnext/patches/v9_0/revert_manufacturing_user_role.py delete mode 100644 erpnext/patches/v9_0/set_pos_profile_name.py delete mode 100644 erpnext/patches/v9_0/set_schedule_date_for_material_request_and_purchase_order.py delete mode 100644 erpnext/patches/v9_0/set_shipping_type_for_existing_shipping_rules.py delete mode 100644 erpnext/patches/v9_0/set_uoms_in_variant_field.py delete mode 100644 erpnext/patches/v9_0/set_variant_item_description.py delete mode 100644 erpnext/patches/v9_0/student_admission_childtable_migrate.py delete mode 100644 erpnext/patches/v9_0/update_employee_loan_details.py delete mode 100644 erpnext/patches/v9_0/update_multi_uom_fields_in_material_request.py delete mode 100644 erpnext/patches/v9_1/__init__.py delete mode 100644 erpnext/patches/v9_1/create_issue_opportunity_type.py delete mode 100644 erpnext/patches/v9_2/__init__.py delete mode 100644 erpnext/patches/v9_2/delete_healthcare_domain_default_items.py delete mode 100644 erpnext/patches/v9_2/delete_process_payroll.py delete mode 100644 erpnext/patches/v9_2/remove_company_from_patient.py delete mode 100644 erpnext/patches/v9_2/rename_net_weight_in_item_master.py delete mode 100644 erpnext/patches/v9_2/rename_translated_domains_in_en.py delete mode 100644 erpnext/patches/v9_2/repost_reserved_qty_for_production.py delete mode 100644 erpnext/patches/v9_2/set_item_name_in_production_order.py diff --git a/erpnext/patches/repair_tools/__init__.py b/erpnext/patches/repair_tools/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/erpnext/patches/repair_tools/set_stock_balance_as_per_serial_no.py b/erpnext/patches/repair_tools/set_stock_balance_as_per_serial_no.py deleted file mode 100644 index 5a421d146fe..00000000000 --- a/erpnext/patches/repair_tools/set_stock_balance_as_per_serial_no.py +++ /dev/null @@ -1,13 +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 - -def execute(): - from erpnext.stock.stock_balance import set_stock_balance_as_per_serial_no - frappe.db.auto_commit_on_many_writes = 1 - - set_stock_balance_as_per_serial_no() - - frappe.db.auto_commit_on_many_writes = 0 diff --git a/erpnext/patches/v10_0/__init__.py b/erpnext/patches/v10_0/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/erpnext/patches/v10_0/add_agriculture_domain.py b/erpnext/patches/v10_0/add_agriculture_domain.py deleted file mode 100644 index c18e69f3e6c..00000000000 --- a/erpnext/patches/v10_0/add_agriculture_domain.py +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - domain = 'Agriculture' - if not frappe.db.exists('Domain', domain): - frappe.get_doc({ - 'doctype': 'Domain', - 'domain': domain - }).insert(ignore_permissions=True) \ No newline at end of file diff --git a/erpnext/patches/v10_0/add_guardian_role_for_parent_portal.py b/erpnext/patches/v10_0/add_guardian_role_for_parent_portal.py deleted file mode 100644 index 0b891f21f44..00000000000 --- a/erpnext/patches/v10_0/add_guardian_role_for_parent_portal.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - # create guardian role - if not frappe.get_value('Role', dict(role_name='Guardian')): - frappe.get_doc({ - 'doctype': 'Role', - 'role_name': 'Guardian', - 'desk_access': 0, - 'restrict_to_domain': 'Education' - }).insert(ignore_permissions=True) - - # set guardian roles in already created users - if frappe.db.exists("Doctype", "Guardian"): - for user in frappe.db.sql_list("""select u.name from `tabUser` u , `tabGuardian` g where g.email_address = u.name"""): - user = frappe.get_doc('User', user) - user.flags.ignore_validate = True - user.flags.ignore_mandatory = True - user.save() diff --git a/erpnext/patches/v10_0/add_non_profit_domain.py b/erpnext/patches/v10_0/add_non_profit_domain.py deleted file mode 100644 index b03d6695154..00000000000 --- a/erpnext/patches/v10_0/add_non_profit_domain.py +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - domain = 'Non Profit' - if not frappe.db.exists('Domain', domain): - frappe.get_doc({ - 'doctype': 'Domain', - 'domain': domain - }).insert(ignore_permissions=True) - - frappe.get_doc({ - 'doctype': 'Role', - 'role_name': 'Non Profit Portal User', - 'desk_access': 0, - 'restrict_to_domain': domain - }).insert(ignore_permissions=True) \ No newline at end of file diff --git a/erpnext/patches/v10_0/allow_operators_in_supplier_scorecard.py b/erpnext/patches/v10_0/allow_operators_in_supplier_scorecard.py deleted file mode 100644 index 827f9bc94fa..00000000000 --- a/erpnext/patches/v10_0/allow_operators_in_supplier_scorecard.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (c) 2019, Frappe and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doc('buying', 'doctype', 'supplier_scorecard_criteria') - frappe.reload_doc('buying', 'doctype', 'supplier_scorecard_scoring_criteria') - frappe.reload_doc('buying', 'doctype', 'supplier_scorecard') - - for criteria in frappe.get_all('Supplier Scorecard Criteria', fields=['name', 'formula'], limit_page_length=None): - frappe.db.set_value('Supplier Scorecard Criteria', criteria.name, - 'formula', criteria.formula.replace('<','<').replace('>','>')) - - for criteria in frappe.get_all('Supplier Scorecard Scoring Criteria', fields=['name', 'formula'], limit_page_length=None): - if criteria.formula: # not mandatory - frappe.db.set_value('Supplier Scorecard Scoring Criteria', criteria.name, - 'formula', criteria.formula.replace('<','<').replace('>','>')) - - for sc in frappe.get_all('Supplier Scorecard', fields=['name', 'weighting_function'], limit_page_length=None): - frappe.db.set_value('Supplier Scorecard', sc.name, 'weighting_function', - sc.weighting_function.replace('<','<').replace('>','>')) \ No newline at end of file diff --git a/erpnext/patches/v10_0/copy_projects_renamed_fields.py b/erpnext/patches/v10_0/copy_projects_renamed_fields.py deleted file mode 100644 index 80db3bdd1ee..00000000000 --- a/erpnext/patches/v10_0/copy_projects_renamed_fields.py +++ /dev/null @@ -1,13 +0,0 @@ -from __future__ import unicode_literals -import frappe -from frappe.model.utils.rename_field import rename_field - -def execute(): - """ copy data from old fields to new """ - frappe.reload_doc("projects", "doctype", "project") - - if frappe.db.has_column('Project', 'total_sales_cost'): - rename_field('Project', "total_sales_cost", "total_sales_amount") - - if frappe.db.has_column('Project', 'total_billing_amount'): - rename_field('Project', "total_billing_amount", "total_billable_amount") \ No newline at end of file diff --git a/erpnext/patches/v10_0/enabled_regional_print_format_based_on_country.py b/erpnext/patches/v10_0/enabled_regional_print_format_based_on_country.py deleted file mode 100644 index 38b04cebc2e..00000000000 --- a/erpnext/patches/v10_0/enabled_regional_print_format_based_on_country.py +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - print_format_mapper = { - 'India': ['GST POS Invoice', 'GST Tax Invoice'], - 'Saudi Arabia': ['Simplified Tax Invoice', 'Detailed Tax Invoice', 'Tax Invoice'], - 'United Arab Emirates': ['Simplified Tax Invoice', 'Detailed Tax Invoice', 'Tax Invoice'] - } - - frappe.db.sql(""" update `tabPrint Format` set disabled = 1 where name - in ('GST POS Invoice', 'GST Tax Invoice', 'Simplified Tax Invoice', 'Detailed Tax Invoice')""") - - for d in frappe.get_all('Company', fields = ["country"], - filters={'country': ('in', ['India', 'Saudi Arabia', 'United Arab Emirates'])}): - if print_format_mapper.get(d.country): - print_formats = print_format_mapper.get(d.country) - frappe.db.sql(""" update `tabPrint Format` set disabled = 0 - where name in (%s)""" % ", ".join(["%s"]*len(print_formats)), tuple(print_formats)) \ No newline at end of file diff --git a/erpnext/patches/v10_0/fix_reserved_qty_for_sub_contract.py b/erpnext/patches/v10_0/fix_reserved_qty_for_sub_contract.py deleted file mode 100644 index c0a9e5eb5bc..00000000000 --- a/erpnext/patches/v10_0/fix_reserved_qty_for_sub_contract.py +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe -from erpnext.stock.utils import get_bin - -def execute(): - frappe.reload_doc("stock", "doctype", "bin") - frappe.reload_doc("buying", "doctype", "purchase_order_item_supplied") - for d in frappe.db.sql(""" - select distinct rm_item_code, reserve_warehouse - from `tabPurchase Order Item Supplied` - where docstatus=1 and reserve_warehouse is not null and reserve_warehouse != ''"""): - - try: - bin_doc = get_bin(d[0], d[1]) - bin_doc.update_reserved_qty_for_sub_contracting() - except: - pass - - for d in frappe.db.sql("""select distinct item_code, source_warehouse - from `tabWork Order Item` - where docstatus=1 and transferred_qty > required_qty - and source_warehouse is not null and source_warehouse != ''""", as_list=1): - - try: - bin_doc = get_bin(d[0], d[1]) - bin_doc.update_reserved_qty_for_production() - except: - pass diff --git a/erpnext/patches/v10_0/recalculate_gross_margin_for_project.py b/erpnext/patches/v10_0/recalculate_gross_margin_for_project.py deleted file mode 100644 index 6d461f3bc97..00000000000 --- a/erpnext/patches/v10_0/recalculate_gross_margin_for_project.py +++ /dev/null @@ -1,14 +0,0 @@ -# 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('projects', 'doctype', 'project') - for d in frappe.db.sql(""" select name from `tabProject` where - ifnull(total_consumed_material_cost, 0 ) > 0 and ifnull(total_billed_amount, 0) > 0""", as_dict=1): - doc = frappe.get_doc("Project", d.name) - doc.calculate_gross_margin() - doc.db_set('gross_margin', doc.gross_margin) - doc.db_set('per_gross_margin', doc.per_gross_margin) \ No newline at end of file diff --git a/erpnext/patches/v10_0/rename_schools_to_education.py b/erpnext/patches/v10_0/rename_schools_to_education.py deleted file mode 100644 index 85c25a89434..00000000000 --- a/erpnext/patches/v10_0/rename_schools_to_education.py +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - # rename the School module as Education - - # rename the school module - if frappe.db.exists('Module Def', 'Schools') and not frappe.db.exists('Module Def', 'Education'): - frappe.rename_doc("Module Def", "Schools", "Education") - - # delete the school module - if frappe.db.exists('Module Def', 'Schools') and frappe.db.exists('Module Def', 'Education'): - frappe.db.sql("""delete from `tabModule Def` where module_name = 'Schools'""") - - - # rename "School Settings" to the "Education Settings - if frappe.db.exists('DocType', 'School Settings'): - frappe.rename_doc("DocType", "School Settings", "Education Settings", force=True) - frappe.reload_doc("education", "doctype", "education_settings") - - # delete the discussion web form if exists - if frappe.db.exists('Web Form', 'Discussion'): - frappe.db.sql("""delete from `tabWeb Form` where name = 'discussion'""") - - # rename the select option field from "School Bus" to "Institute's Bus" - frappe.reload_doc("education", "doctype", "Program Enrollment") - if "mode_of_transportation" in frappe.db.get_table_columns("Program Enrollment"): - frappe.db.sql("""update `tabProgram Enrollment` set mode_of_transportation = "Institute's Bus" - where mode_of_transportation = "School Bus" """) diff --git a/erpnext/patches/v10_0/repost_gle_for_purchase_receipts_with_rejected_items.py b/erpnext/patches/v10_0/repost_gle_for_purchase_receipts_with_rejected_items.py deleted file mode 100644 index e6546e386b9..00000000000 --- a/erpnext/patches/v10_0/repost_gle_for_purchase_receipts_with_rejected_items.py +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe, erpnext - -def execute(): - for company in frappe.get_all("Company"): - if not erpnext.is_perpetual_inventory_enabled(company.name): - continue - - acc_frozen_upto = frappe.db.get_value("Accounts Settings", None, "acc_frozen_upto") or "1900-01-01" - pr_with_rejected_warehouse = frappe.db.sql(""" - select pr.name - from `tabPurchase Receipt` pr, `tabPurchase Receipt Item` pr_item - where pr.name = pr_item.parent - and pr.posting_date > %s - and pr.docstatus=1 - and pr.company = %s - and pr_item.rejected_qty > 0 - """, (acc_frozen_upto, company.name), as_dict=1) - - for d in pr_with_rejected_warehouse: - doc = frappe.get_doc("Purchase Receipt", d.name) - - doc.docstatus = 2 - doc.make_gl_entries_on_cancel() - - - # update gl entries for submit state of PR - doc.docstatus = 1 - doc.make_gl_entries() diff --git a/erpnext/patches/v10_0/repost_requested_qty_for_non_stock_uom_items.py b/erpnext/patches/v10_0/repost_requested_qty_for_non_stock_uom_items.py deleted file mode 100644 index 4fe4e97cf5b..00000000000 --- a/erpnext/patches/v10_0/repost_requested_qty_for_non_stock_uom_items.py +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright (c) 2019, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - from erpnext.stock.stock_balance import update_bin_qty, get_indented_qty - - count=0 - for item_code, warehouse in frappe.db.sql("""select distinct item_code, warehouse - from `tabMaterial Request Item` where docstatus = 1 and stock_uom<>uom"""): - try: - count += 1 - update_bin_qty(item_code, warehouse, { - "indented_qty": get_indented_qty(item_code, warehouse), - }) - if count % 200 == 0: - frappe.db.commit() - except: - frappe.db.rollback() diff --git a/erpnext/patches/v10_0/set_auto_created_serial_no_in_stock_entry.py b/erpnext/patches/v10_0/set_auto_created_serial_no_in_stock_entry.py deleted file mode 100644 index c6470f21d7c..00000000000 --- a/erpnext/patches/v10_0/set_auto_created_serial_no_in_stock_entry.py +++ /dev/null @@ -1,56 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - serialised_items = [d.name for d in frappe.get_all("Item", filters={"has_serial_no": 1})] - - if not serialised_items: - return - - for dt in ["Stock Entry Detail", "Purchase Receipt Item", "Purchase Invoice Item"]: - cond = "" - if dt=="Purchase Invoice Item": - cond = """ and parent in (select name from `tabPurchase Invoice` - where `tabPurchase Invoice`.name = `tabPurchase Invoice Item`.parent and update_stock=1)""" - - item_rows = frappe.db.sql(""" - select name - from `tab{0}` - where conversion_factor != 1 - and docstatus = 1 - and ifnull(serial_no, '') = '' - and item_code in ({1}) - {2} - """.format(dt, ', '.join(['%s']*len(serialised_items)), cond), tuple(serialised_items)) - - if item_rows: - sle_serial_nos = dict(frappe.db.sql(""" - select voucher_detail_no, serial_no - from `tabStock Ledger Entry` - where ifnull(serial_no, '') != '' - and voucher_detail_no in (%s) - """.format(', '.join(['%s']*len(item_rows))), - tuple([d[0] for d in item_rows]))) - - batch_size = 100 - for i in range(0, len(item_rows), batch_size): - batch_item_rows = item_rows[i:i + batch_size] - when_then = [] - for item_row in batch_item_rows: - - when_then.append('WHEN `name` = "{row_name}" THEN "{value}"'.format( - row_name=item_row[0], - value=sle_serial_nos.get(item_row[0]))) - - frappe.db.sql(""" - update - `tab{doctype}` - set - serial_no = CASE {when_then_cond} ELSE `serial_no` END - """.format( - doctype = dt, - when_then_cond=" ".join(when_then) - )) \ No newline at end of file diff --git a/erpnext/patches/v10_0/set_b2c_limit.py b/erpnext/patches/v10_0/set_b2c_limit.py deleted file mode 100644 index 5d964e681ab..00000000000 --- a/erpnext/patches/v10_0/set_b2c_limit.py +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doc("regional", "doctype", "gst_settings") - frappe.reload_doc("accounts", "doctype", "gst_account") - gst_settings = frappe.get_doc("GST Settings") - gst_settings.b2c_limit = 250000 - gst_settings.save() diff --git a/erpnext/patches/v10_0/set_default_payment_terms_based_on_company.py b/erpnext/patches/v10_0/set_default_payment_terms_based_on_company.py deleted file mode 100644 index a90e096390a..00000000000 --- a/erpnext/patches/v10_0/set_default_payment_terms_based_on_company.py +++ /dev/null @@ -1,37 +0,0 @@ -from __future__ import unicode_literals -import frappe -from erpnext.patches.v8_10.change_default_customer_credit_days import make_payment_term, make_template - -def execute(): - for dt in ("Company", "Customer Group"): - frappe.reload_doc("setup", "doctype", frappe.scrub(dt)) - - credit_records = frappe.db.sql(""" - SELECT DISTINCT `credit_days`, `credit_days_based_on`, `name` - from `tab{0}` - where - ((credit_days_based_on='Fixed Days' or credit_days_based_on is null) and credit_days is not null) - or credit_days_based_on='Last Day of the Next Month' - """.format(dt), as_dict=1) - - for d in credit_records: - template = create_payment_terms_template(d) - - frappe.db.sql(""" - update `tab{0}` - set `payment_terms` = %s - where name = %s - """.format(dt), (template.name, d.name)) - -def create_payment_terms_template(data): - if data.credit_days_based_on == "Fixed Days": - pyt_template_name = 'Default Payment Term - N{0}'.format(data.credit_days) - else: - pyt_template_name = 'Default Payment Term - EO2M' - - if not frappe.db.exists("Payment Terms Template", pyt_template_name): - payment_term = make_payment_term(data.credit_days, data.credit_days_based_on) - template = make_template(payment_term) - else: - template = frappe.get_doc("Payment Terms Template", pyt_template_name) - return template \ No newline at end of file diff --git a/erpnext/patches/v10_0/set_discount_amount.py b/erpnext/patches/v10_0/set_discount_amount.py deleted file mode 100644 index d5e2c5a84b8..00000000000 --- a/erpnext/patches/v10_0/set_discount_amount.py +++ /dev/null @@ -1,35 +0,0 @@ -from __future__ import unicode_literals - -import frappe - -def execute(): - frappe.reload_doc("accounts", "doctype", "sales_invoice_item") - frappe.reload_doc('accounts', 'doctype', 'purchase_invoice_item') - frappe.reload_doc('buying', 'doctype', 'purchase_order_item') - frappe.reload_doc('buying', 'doctype', 'supplier_quotation_item') - frappe.reload_doc('selling', 'doctype', 'sales_order_item') - frappe.reload_doc('selling', 'doctype', 'quotation_item') - frappe.reload_doc('stock', 'doctype', 'delivery_note_item') - frappe.reload_doc('stock', 'doctype', 'purchase_receipt_item') - - selling_doctypes = ["Sales Order Item", "Sales Invoice Item", "Delivery Note Item", "Quotation Item"] - buying_doctypes = ["Purchase Order Item", "Purchase Invoice Item", "Purchase Receipt Item", "Supplier Quotation Item"] - - for doctype in selling_doctypes: - frappe.db.sql(''' - UPDATE - `tab%s` - SET - discount_amount = if(rate_with_margin > 0, rate_with_margin, price_list_rate) * discount_percentage / 100 - WHERE - discount_percentage > 0 - ''' % (doctype)) - for doctype in buying_doctypes: - frappe.db.sql(''' - UPDATE - `tab%s` - SET - discount_amount = price_list_rate * discount_percentage / 100 - WHERE - discount_percentage > 0 - ''' % (doctype)) \ No newline at end of file diff --git a/erpnext/patches/v10_0/set_numeric_ranges_in_template_if_blank.py b/erpnext/patches/v10_0/set_numeric_ranges_in_template_if_blank.py deleted file mode 100644 index 6825f19d74d..00000000000 --- a/erpnext/patches/v10_0/set_numeric_ranges_in_template_if_blank.py +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - item_numeric_attributes = frappe.db.sql(""" - select name, numeric_values, from_range, to_range, increment - from `tabItem Attribute` - where numeric_values = 1 - """, as_dict=1) - - for d in item_numeric_attributes: - frappe.db.sql(""" - update `tabItem Variant Attribute` - set - from_range = CASE - WHEN from_range = 0 THEN %(from_range)s - ELSE from_range - END, - to_range = CASE - WHEN to_range = 0 THEN %(to_range)s - ELSE to_range - END, - increment = CASE - WHEN increment = 0 THEN %(increment)s - ELSE increment - END, - numeric_values = %(numeric_values)s - where - attribute = %(name)s - and exists(select name from tabItem - where name=`tabItem Variant Attribute`.parent and has_variants=1) - """, d) \ No newline at end of file diff --git a/erpnext/patches/v10_0/set_primary_contact_for_customer.py b/erpnext/patches/v10_0/set_primary_contact_for_customer.py deleted file mode 100644 index ae0b31c21f6..00000000000 --- a/erpnext/patches/v10_0/set_primary_contact_for_customer.py +++ /dev/null @@ -1,21 +0,0 @@ -# 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_doctype('Customer') - - frappe.db.sql(""" - update - `tabCustomer`, ( - select `tabContact`.name, `tabContact`.mobile_no, `tabContact`.email_id, - `tabDynamic Link`.link_name from `tabContact`, `tabDynamic Link` - where `tabContact`.name = `tabDynamic Link`.parent and - `tabDynamic Link`.link_doctype = 'Customer' and `tabContact`.is_primary_contact = 1 - ) as contact - set - `tabCustomer`.customer_primary_contact = contact.name, - `tabCustomer`.mobile_no = contact.mobile_no, `tabCustomer`.email_id = contact.email_id - where `tabCustomer`.name = contact.link_name""") \ No newline at end of file diff --git a/erpnext/patches/v10_0/set_qty_in_transactions_based_on_serial_no_input.py b/erpnext/patches/v10_0/set_qty_in_transactions_based_on_serial_no_input.py deleted file mode 100644 index 083b7f4b201..00000000000 --- a/erpnext/patches/v10_0/set_qty_in_transactions_based_on_serial_no_input.py +++ /dev/null @@ -1,21 +0,0 @@ -# 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("stock", "doctype", "stock_settings") - - ss = frappe.get_doc("Stock Settings") - ss.set_qty_in_transactions_based_on_serial_no_input = 1 - - if ss.default_warehouse \ - and not frappe.db.exists("Warehouse", ss.default_warehouse): - ss.default_warehouse = None - - if ss.stock_uom and not frappe.db.exists("UOM", ss.stock_uom): - ss.stock_uom = None - - ss.flags.ignore_mandatory = True - ss.save() \ No newline at end of file diff --git a/erpnext/patches/v10_0/set_student_party_type.py b/erpnext/patches/v10_0/set_student_party_type.py deleted file mode 100644 index 08376ae894b..00000000000 --- a/erpnext/patches/v10_0/set_student_party_type.py +++ /dev/null @@ -1,8 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - if not frappe.db.exists("Party Type", "Student"): - party = frappe.new_doc("Party Type") - party.party_type = "Student" - party.save() diff --git a/erpnext/patches/v10_0/setup_vat_for_uae_and_saudi_arabia.py b/erpnext/patches/v10_0/setup_vat_for_uae_and_saudi_arabia.py deleted file mode 100644 index a8d90499d88..00000000000 --- a/erpnext/patches/v10_0/setup_vat_for_uae_and_saudi_arabia.py +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe -from erpnext.setup.doctype.company.company import install_country_fixtures - -def execute(): - frappe.reload_doc("accounts", "doctype", "account") - frappe.reload_doc("accounts", "doctype", "payment_schedule") - for d in frappe.get_all('Company', - filters={'country': ('in', ['Saudi Arabia', 'United Arab Emirates'])}): - install_country_fixtures(d.name) \ No newline at end of file diff --git a/erpnext/patches/v10_0/show_leaves_of_all_department_members_in_calendar.py b/erpnext/patches/v10_0/show_leaves_of_all_department_members_in_calendar.py deleted file mode 100644 index 7e2ff7a8a7f..00000000000 --- a/erpnext/patches/v10_0/show_leaves_of_all_department_members_in_calendar.py +++ /dev/null @@ -1,6 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doc("hr", "doctype", "hr_settings") - frappe.db.set_value("HR Settings", None, "show_leaves_of_all_department_members_in_calendar", 1) \ No newline at end of file diff --git a/erpnext/patches/v10_0/taxes_issue_with_pos.py b/erpnext/patches/v10_0/taxes_issue_with_pos.py deleted file mode 100644 index 2a3275ac2ce..00000000000 --- a/erpnext/patches/v10_0/taxes_issue_with_pos.py +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - for d in frappe.get_all('Sales Invoice', fields=["name"], - filters = {'is_pos':1, 'docstatus': 1, 'creation': ('>', '2018-04-23')}): - doc = frappe.get_doc('Sales Invoice', d.name) - if (not doc.taxes and doc.taxes_and_charges and doc.pos_profile and doc.outstanding_amount != 0 and - frappe.db.get_value('POS Profile', doc.pos_profile, 'taxes_and_charges', cache=True) == doc.taxes_and_charges): - - doc.append_taxes_from_master() - doc.calculate_taxes_and_totals() - for d in doc.taxes: - d.db_update() - - doc.db_update() - - delete_gle_for_voucher(doc.name) - doc.make_gl_entries() - -def delete_gle_for_voucher(voucher_no): - frappe.db.sql("""delete from `tabGL Entry` where voucher_no = %(voucher_no)s""", - {'voucher_no': voucher_no}) \ No newline at end of file diff --git a/erpnext/patches/v10_0/update_address_template_for_india.py b/erpnext/patches/v10_0/update_address_template_for_india.py deleted file mode 100644 index 1ddca937609..00000000000 --- a/erpnext/patches/v10_0/update_address_template_for_india.py +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe -from erpnext.regional.address_template.setup import set_up_address_templates - -def execute(): - if frappe.db.get_value('Company', {'country': 'India'}, 'name'): - address_template = frappe.db.get_value('Address Template', 'India', 'template') - if not address_template or "gstin" not in address_template: - set_up_address_templates(default_country='India') diff --git a/erpnext/patches/v10_0/update_assessment_plan.py b/erpnext/patches/v10_0/update_assessment_plan.py deleted file mode 100644 index 174623c1a48..00000000000 --- a/erpnext/patches/v10_0/update_assessment_plan.py +++ /dev/null @@ -1,17 +0,0 @@ -# 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('education', 'doctype', 'assessment_plan') - - frappe.db.sql(""" - UPDATE `tabAssessment Plan` as ap - INNER JOIN `tabStudent Group` as sg ON sg.name = ap.student_group - SET ap.academic_term = sg.academic_term, - ap.academic_year = sg.academic_year, - ap.program = sg.program - WHERE ap.docstatus = 1 - """) \ No newline at end of file diff --git a/erpnext/patches/v10_0/update_assessment_result.py b/erpnext/patches/v10_0/update_assessment_result.py deleted file mode 100644 index 96218db972c..00000000000 --- a/erpnext/patches/v10_0/update_assessment_result.py +++ /dev/null @@ -1,20 +0,0 @@ -# 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('education', 'doctype', 'assessment_result') - - frappe.db.sql(""" - UPDATE `tabAssessment Result` AS ar - INNER JOIN `tabAssessment Plan` AS ap ON ap.name = ar.assessment_plan - SET ar.academic_term = ap.academic_term, - ar.academic_year = ap.academic_year, - ar.program = ap.program, - ar.course = ap.course, - ar.assessment_group = ap.assessment_group, - ar.student_group = ap.student_group - WHERE ap.docstatus = 1 - """) \ No newline at end of file diff --git a/erpnext/patches/v10_0/update_asset_calculate_depreciation.py b/erpnext/patches/v10_0/update_asset_calculate_depreciation.py deleted file mode 100644 index b947a40b4a3..00000000000 --- a/erpnext/patches/v10_0/update_asset_calculate_depreciation.py +++ /dev/null @@ -1,12 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doc('assets', 'doctype', 'asset') - frappe.reload_doc('assets', 'doctype', 'depreciation_schedule') - - frappe.db.sql(""" - update tabAsset a - set calculate_depreciation = 1 - where exists(select ds.name from `tabDepreciation Schedule` ds where ds.parent=a.name) - """) \ No newline at end of file diff --git a/erpnext/patches/v10_0/update_hub_connector_domain.py b/erpnext/patches/v10_0/update_hub_connector_domain.py deleted file mode 100644 index baf580a3699..00000000000 --- a/erpnext/patches/v10_0/update_hub_connector_domain.py +++ /dev/null @@ -1,10 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - if frappe.db.table_exists("Data Migration Connector"): - frappe.db.sql(""" - UPDATE `tabData Migration Connector` - SET hostname = 'https://hubmarket.org' - WHERE connector_name = 'Hub Connector' - """) \ No newline at end of file diff --git a/erpnext/patches/v10_0/update_lft_rgt_for_employee.py b/erpnext/patches/v10_0/update_lft_rgt_for_employee.py deleted file mode 100644 index 46ca786e0d6..00000000000 --- a/erpnext/patches/v10_0/update_lft_rgt_for_employee.py +++ /dev/null @@ -1,9 +0,0 @@ -from __future__ import unicode_literals -import frappe -from frappe.utils.nestedset import rebuild_tree - -def execute(): - """ assign lft and rgt appropriately """ - frappe.reload_doc("hr", "doctype", "employee") - - rebuild_tree("Employee", "reports_to") \ No newline at end of file diff --git a/erpnext/patches/v10_0/update_project_in_sle.py b/erpnext/patches/v10_0/update_project_in_sle.py deleted file mode 100644 index 08c64f18d80..00000000000 --- a/erpnext/patches/v10_0/update_project_in_sle.py +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - for doctype in ['Sales Invoice', 'Delivery Note', 'Stock Entry']: - frappe.db.sql(""" update - `tabStock Ledger Entry` sle, `tab{0}` parent_doc - set - sle.project = parent_doc.project - where - sle.voucher_no = parent_doc.name and sle.voucher_type = %s and sle.project is null - and parent_doc.project is not null and parent_doc.project != ''""".format(doctype), doctype) diff --git a/erpnext/patches/v10_0/update_reserved_qty_for_purchase_order.py b/erpnext/patches/v10_0/update_reserved_qty_for_purchase_order.py deleted file mode 100644 index 7b2c36698a2..00000000000 --- a/erpnext/patches/v10_0/update_reserved_qty_for_purchase_order.py +++ /dev/null @@ -1,53 +0,0 @@ -from __future__ import unicode_literals -import frappe -from erpnext.stock.utils import get_bin - -def execute(): - po_item = list(frappe.db.sql((""" - select distinct po.name as poname, poitem.rm_item_code as rm_item_code, po.company - from `tabPurchase Order` po, `tabPurchase Order Item Supplied` poitem - where po.name = poitem.parent - and po.is_subcontracted = "Yes" - and po.docstatus = 1"""), as_dict=1)) - if not po_item: - return - - frappe.reload_doc("stock", "doctype", "bin") - frappe.reload_doc("buying", "doctype", "purchase_order_item_supplied") - company_warehouse = frappe._dict(frappe.db.sql("""select company, min(name) from `tabWarehouse` - where is_group = 0 group by company""")) - - items = list(set([d.rm_item_code for d in po_item])) - item_wh = frappe._dict(frappe.db.sql("""select item_code, default_warehouse - from `tabItem` where name in ({0})""".format(", ".join(["%s"] * len(items))), items)) - - # Update reserved warehouse - for item in po_item: - reserve_warehouse = get_warehouse(item.rm_item_code, item.company, company_warehouse, item_wh) - frappe.db.sql("""update `tabPurchase Order Item Supplied` - set reserve_warehouse = %s - where parent = %s and rm_item_code = %s - """, (reserve_warehouse, item["poname"], item["rm_item_code"])) - - # Update bin - item_wh_bin = frappe.db.sql((""" - select distinct poitemsup.rm_item_code as rm_item_code, - poitemsup.reserve_warehouse as reserve_warehouse - from `tabPurchase Order` po, `tabPurchase Order Item Supplied` poitemsup - where po.name = poitemsup.parent - and po.is_subcontracted = "Yes" - and po.docstatus = 1"""), as_dict=1) - for d in item_wh_bin: - try: - stock_bin = get_bin(d["rm_item_code"], d["reserve_warehouse"]) - stock_bin.update_reserved_qty_for_sub_contracting() - except: - pass - -def get_warehouse(item_code, company, company_warehouse, item_wh): - reserve_warehouse = item_wh.get(item_code) - if frappe.db.get_value("Warehouse", reserve_warehouse, "company") != company: - reserve_warehouse = None - if not reserve_warehouse: - reserve_warehouse = company_warehouse.get(company) - return reserve_warehouse diff --git a/erpnext/patches/v10_0/update_sales_order_link_to_purchase_order.py b/erpnext/patches/v10_0/update_sales_order_link_to_purchase_order.py deleted file mode 100644 index b4f58384bfe..00000000000 --- a/erpnext/patches/v10_0/update_sales_order_link_to_purchase_order.py +++ /dev/null @@ -1,18 +0,0 @@ -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doc("buying", "doctype", "supplier_quotation_item") - - for doctype in ['Purchase Order','Supplier Quotation']: - frappe.db.sql(""" - Update - `tab{doctype} Item`, `tabMaterial Request Item` - set - `tab{doctype} Item`.sales_order = `tabMaterial Request Item`.sales_order - where - `tab{doctype} Item`.material_request= `tabMaterial Request Item`.parent - and `tab{doctype} Item`.material_request_item = `tabMaterial Request Item`.name - and `tabMaterial Request Item`.sales_order is not null""".format(doctype=doctype)) \ No newline at end of file diff --git a/erpnext/patches/v10_0/update_status_for_multiple_source_in_po.py b/erpnext/patches/v10_0/update_status_for_multiple_source_in_po.py deleted file mode 100644 index fd3be08b89b..00000000000 --- a/erpnext/patches/v10_0/update_status_for_multiple_source_in_po.py +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - - - # update the sales order item in the material request - frappe.reload_doc('stock', 'doctype', 'material_request_item') - frappe.db.sql('''update `tabMaterial Request Item` mri, `tabSales Order Item` soi - set mri.sales_order_item = soi.name - where ifnull(mri.sales_order, "")!="" and soi.parent=mri.sales_order - and soi.item_code=mri.item_code and mri.docstatus=1 - ''') - - # update the sales order item in the purchase order - frappe.db.sql('''update `tabPurchase Order Item` poi, `tabSales Order Item` soi - set poi.sales_order_item = soi.name - where ifnull(poi.sales_order, "")!="" and soi.parent=poi.sales_order - and soi.item_code=poi.item_code and poi.docstatus = 1 - ''') - - # Update the status in material request and sales order - po_list = frappe.db.sql(''' - select parent from `tabPurchase Order Item` where ifnull(material_request, "")!="" and - ifnull(sales_order, "")!="" and docstatus=1 - ''',as_dict=1) - - for po in list(set([d.get("parent") for d in po_list if d.get("parent")])): - try: - po_doc = frappe.get_doc("Purchase Order", po) - - # update the so in the status updater - po_doc.update_status_updater() - po_doc.update_qty(update_modified=False) - - except Exception: - pass diff --git a/erpnext/patches/v10_0/update_status_in_purchase_receipt.py b/erpnext/patches/v10_0/update_status_in_purchase_receipt.py deleted file mode 100644 index a0bdd9e2cc1..00000000000 --- a/erpnext/patches/v10_0/update_status_in_purchase_receipt.py +++ /dev/null @@ -1,8 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doc("stock", "doctype", "purchase_receipt") - frappe.db.sql(''' - UPDATE `tabPurchase Receipt` SET status = "Completed" WHERE per_billed = 100 AND docstatus = 1 - ''') \ No newline at end of file diff --git a/erpnext/patches/v10_0/update_territory_and_customer_group.py b/erpnext/patches/v10_0/update_territory_and_customer_group.py deleted file mode 100644 index 7f3dae991d2..00000000000 --- a/erpnext/patches/v10_0/update_territory_and_customer_group.py +++ /dev/null @@ -1,29 +0,0 @@ -from __future__ import unicode_literals -import frappe -from frappe.model.rename_doc import get_fetch_fields - -def execute(): - ignore_doctypes = ["Lead", "Opportunity", "POS Profile", "Tax Rule", "Pricing Rule"] - customers = frappe.get_all('Customer', fields=["name", "customer_group"]) - customer_group_fetch = get_fetch_fields('Customer', 'Customer Group', ignore_doctypes) - - batch_size = 1000 - for i in range(0, len(customers), batch_size): - batch_customers = customers[i:i + batch_size] - for d in customer_group_fetch: - when_then = [] - for customer in batch_customers: - value = frappe.db.escape(frappe.as_unicode(customer.get("customer_group"))) - - when_then.append(''' - WHEN `%s` = %s and %s != %s - THEN %s - '''%(d["master_fieldname"], frappe.db.escape(frappe.as_unicode(customer.name)), - d["linked_to_fieldname"], value, value)) - - frappe.db.sql(""" - update - `tab%s` - set - %s = CASE %s ELSE `%s` END - """%(d['doctype'], d.linked_to_fieldname, " ".join(when_then), d.linked_to_fieldname)) diff --git a/erpnext/patches/v10_0/update_user_image_in_employee.py b/erpnext/patches/v10_0/update_user_image_in_employee.py deleted file mode 100644 index 72d5d2a857b..00000000000 --- a/erpnext/patches/v10_0/update_user_image_in_employee.py +++ /dev/null @@ -1,19 +0,0 @@ -# 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('hr', 'doctype', 'employee') - - frappe.db.sql(""" - UPDATE - `tabEmployee`, `tabUser` - SET - `tabEmployee`.image = `tabUser`.user_image - WHERE - `tabEmployee`.user_id = `tabUser`.name and - `tabEmployee`.user_id is not null and - `tabEmployee`.user_id != '' and `tabEmployee`.image is null - """) diff --git a/erpnext/patches/v10_0/update_warehouse_address_details.py b/erpnext/patches/v10_0/update_warehouse_address_details.py deleted file mode 100644 index b982b9a662f..00000000000 --- a/erpnext/patches/v10_0/update_warehouse_address_details.py +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - warehouse = frappe.db.sql("""select name, email_id, phone_no, mobile_no, address_line_1, - address_line_2, city, state, pin from `tabWarehouse` where ifnull(address_line_1, '') != '' - or ifnull(mobile_no, '') != '' - or ifnull(email_id, '') != '' """, as_dict=1) - - for d in warehouse: - try: - address = frappe.new_doc('Address') - address.name = d.name - address.address_title = d.name - address.address_line1 = d.address_line_1 - address.city = d.city - address.state = d.state - address.pincode = d.pin - address.db_insert() - address.append('links',{'link_doctype':'Warehouse','link_name':d.name}) - address.links[0].db_insert() - if d.name and (d.email_id or d.mobile_no or d.phone_no): - contact = frappe.new_doc('Contact') - contact.name = d.name - contact.first_name = d.name - contact.mobile_no = d.mobile_no - contact.email_id = d.email_id - contact.phone = d.phone_no - contact.db_insert() - contact.append('links',{'link_doctype':'Warehouse','link_name':d.name}) - contact.links[0].db_insert() - except frappe.DuplicateEntryError: - pass - \ No newline at end of file diff --git a/erpnext/patches/v10_1/__init__.py b/erpnext/patches/v10_1/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/erpnext/patches/v11_0/__init__.py b/erpnext/patches/v11_0/__init__.py deleted file mode 100644 index baffc488252..00000000000 --- a/erpnext/patches/v11_0/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from __future__ import unicode_literals diff --git a/erpnext/patches/v11_0/remove_subscriber_doctype.py b/erpnext/patches/v11_0/remove_subscriber_doctype.py deleted file mode 100644 index 4839a20f91f..00000000000 --- a/erpnext/patches/v11_0/remove_subscriber_doctype.py +++ /dev/null @@ -1,16 +0,0 @@ -from __future__ import unicode_literals -import frappe -from frappe.model.utils.rename_field import rename_field - -def execute(): - """ copy subscribe field to customer """ - frappe.reload_doc("accounts","doctype","subscription") - - if frappe.db.exists("DocType", "Subscriber"): - if frappe.db.has_column('Subscription','subscriber'): - frappe.db.sql(""" - update `tabSubscription` s1 - set customer=(select customer from tabSubscriber where name=s1.subscriber) - """) - - frappe.delete_doc("DocType", "Subscriber") \ No newline at end of file diff --git a/erpnext/patches/v11_1/__init__.py b/erpnext/patches/v11_1/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/erpnext/patches/v12_0/__init__.py b/erpnext/patches/v12_0/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/erpnext/patches/v13_0/__init__.py b/erpnext/patches/v13_0/__init__.py deleted file mode 100644 index baffc488252..00000000000 --- a/erpnext/patches/v13_0/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from __future__ import unicode_literals diff --git a/erpnext/patches/v4_0/__init__.py b/erpnext/patches/v4_0/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/erpnext/patches/v4_0/apply_user_permissions.py b/erpnext/patches/v4_0/apply_user_permissions.py deleted file mode 100644 index 3c5d612c181..00000000000 --- a/erpnext/patches/v4_0/apply_user_permissions.py +++ /dev/null @@ -1,50 +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 erpnext.hr.doctype.employee.employee import EmployeeUserDisabledError - -def execute(): - update_hr_permissions() - update_permissions() - remove_duplicate_user_permissions() - frappe.clear_cache() - -def update_hr_permissions(): - # add set user permissions rights to HR Manager - frappe.db.sql("""update `tabDocPerm` set `set_user_permissions`=1 where parent in ('Employee', 'Leave Application') - and role='HR Manager' and permlevel=0 and `read`=1""") - docperm_meta = frappe.get_meta('DocPerm') - if docperm_meta.get_field('apply_user_permissions'): - # apply user permissions on Employee and Leave Application - frappe.db.sql("""update `tabDocPerm` set `apply_user_permissions`=1 where parent in ('Employee', 'Leave Application') - and role in ('Employee', 'Leave Approver') and permlevel=0 and `read`=1""") - - frappe.clear_cache() - - # save employees to run on_update events - for employee in frappe.db.sql_list("""select name from `tabEmployee` where docstatus < 2"""): - try: - emp = frappe.get_doc("Employee", employee) - emp.flags.ignore_mandatory = True - emp.save() - except EmployeeUserDisabledError: - pass - -def update_permissions(): - # clear match conditions other than owner - frappe.db.sql("""update tabDocPerm set `match`='' - where ifnull(`match`,'') not in ('', 'owner')""") - -def remove_duplicate_user_permissions(): - # remove duplicate user_permissions (if they exist) - for d in frappe.db.sql("""select parent, defkey, defvalue, - count(*) as cnt from tabDefaultValue - where parent not in ('__global', '__default') - group by parent, defkey, defvalue""", as_dict=1): - if d.cnt > 1: - # order by parenttype so that user permission does not get removed! - frappe.db.sql("""delete from tabDefaultValue where `parent`=%s and `defkey`=%s and - `defvalue`=%s order by parenttype limit %s""", (d.parent, d.defkey, d.defvalue, d.cnt-1)) - diff --git a/erpnext/patches/v4_0/countrywise_coa.py b/erpnext/patches/v4_0/countrywise_coa.py deleted file mode 100644 index f45e6028c87..00000000000 --- a/erpnext/patches/v4_0/countrywise_coa.py +++ /dev/null @@ -1,29 +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 - -def execute(): - frappe.reload_doc("setup", 'doctype', "company") - frappe.reload_doc("accounts", 'doctype', "account") - - frappe.db.sql("""update tabAccount set account_type='Cash' - where account_type='Bank or Cash' and account_name in ('Cash', 'Cash In Hand')""") - - frappe.db.sql("""update tabAccount set account_type='Stock' - where account_name = 'Stock Assets'""") - - ac_types = {"Fixed Asset Account": "Fixed Asset", "Bank or Cash": "Bank"} - for old, new in ac_types.items(): - frappe.db.sql("""update tabAccount set account_type=%s - where account_type=%s""", (new, old)) - - try: - frappe.db.sql("""update `tabAccount` set report_type = - if(is_pl_account='Yes', 'Profit and Loss', 'Balance Sheet')""") - - frappe.db.sql("""update `tabAccount` set balance_must_be=debit_or_credit - where ifnull(allow_negative_balance, 0) = 0""") - except: - pass diff --git a/erpnext/patches/v4_0/create_custom_fields_for_india_specific_fields.py b/erpnext/patches/v4_0/create_custom_fields_for_india_specific_fields.py deleted file mode 100644 index fe50e444b52..00000000000 --- a/erpnext/patches/v4_0/create_custom_fields_for_india_specific_fields.py +++ /dev/null @@ -1,63 +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.custom.doctype.custom_field.custom_field import create_custom_field_if_values_exist - -def execute(): - frappe.reload_doc("stock", "doctype", "purchase_receipt") - frappe.reload_doc("hr", "doctype", "employee") - frappe.reload_doc("Payroll", "doctype", "salary_slip") - - india_specific_fields = { - "Purchase Receipt": [{ - "label": "Supplier Shipment No", - "fieldname": "challan_no", - "fieldtype": "Data", - "insert_after": "is_subcontracted" - }, { - "label": "Supplier Shipment Date", - "fieldname": "challan_date", - "fieldtype": "Date", - "insert_after": "is_subcontracted" - }], - "Employee": [{ - "label": "PAN Number", - "fieldname": "pan_number", - "fieldtype": "Data", - "insert_after": "company_email" - }, { - "label": "Gratuity LIC Id", - "fieldname": "gratuity_lic_id", - "fieldtype": "Data", - "insert_after": "company_email" - }, { - "label": "Esic Card No", - "fieldname": "esic_card_no", - "fieldtype": "Data", - "insert_after": "bank_ac_no" - }, { - "label": "PF Number", - "fieldname": "pf_number", - "fieldtype": "Data", - "insert_after": "bank_ac_no" - }], - "Salary Slip": [{ - "label": "Esic No", - "fieldname": "esic_no", - "fieldtype": "Data", - "insert_after": "letter_head", - "permlevel": 1 - }, { - "label": "PF Number", - "fieldname": "pf_no", - "fieldtype": "Data", - "insert_after": "letter_head", - "permlevel": 1 - }] - } - - for dt, docfields in india_specific_fields.items(): - for df in docfields: - create_custom_field_if_values_exist(dt, df) diff --git a/erpnext/patches/v4_0/create_price_list_if_missing.py b/erpnext/patches/v4_0/create_price_list_if_missing.py deleted file mode 100644 index 039e52111c9..00000000000 --- a/erpnext/patches/v4_0/create_price_list_if_missing.py +++ /dev/null @@ -1,35 +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 _ -from frappe.utils.nestedset import get_root_of - -def execute(): - # setup not complete - if not frappe.db.sql("""select name from tabCompany limit 1"""): - return - - if "shopping_cart" in frappe.get_installed_apps(): - frappe.reload_doc("shopping_cart", "doctype", "shopping_cart_settings") - - if not frappe.db.sql("select name from `tabPrice List` where buying=1"): - create_price_list(_("Standard Buying"), buying=1) - - if not frappe.db.sql("select name from `tabPrice List` where selling=1"): - create_price_list(_("Standard Selling"), selling=1) - -def create_price_list(pl_name, buying=0, selling=0): - price_list = frappe.get_doc({ - "doctype": "Price List", - "price_list_name": pl_name, - "enabled": 1, - "buying": buying, - "selling": selling, - "currency": frappe.db.get_default("currency"), - "territories": [{ - "territory": get_root_of("Territory") - }] - }) - price_list.insert() diff --git a/erpnext/patches/v4_0/customer_discount_to_pricing_rule.py b/erpnext/patches/v4_0/customer_discount_to_pricing_rule.py deleted file mode 100644 index 1b260c48cc1..00000000000 --- a/erpnext/patches/v4_0/customer_discount_to_pricing_rule.py +++ /dev/null @@ -1,33 +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.utils.nestedset import get_root_of - -def execute(): - frappe.reload_doc("accounts", "doctype", "pricing_rule") - - frappe.db.auto_commit_on_many_writes = True - - default_item_group = get_root_of("Item Group") - - for d in frappe.db.sql("""select * from `tabCustomer Discount` - where ifnull(parent, '') != ''""", as_dict=1): - if not d.discount: - continue - - frappe.get_doc({ - "doctype": "Pricing Rule", - "apply_on": "Item Group", - "item_group": d.item_group or default_item_group, - "applicable_for": "Customer", - "customer": d.parent, - "price_or_discount": "Discount Percentage", - "discount_percentage": d.discount, - "selling": 1 - }).insert() - - frappe.db.auto_commit_on_many_writes = False - - frappe.delete_doc("DocType", "Customer Discount") diff --git a/erpnext/patches/v4_0/fields_to_be_renamed.py b/erpnext/patches/v4_0/fields_to_be_renamed.py deleted file mode 100644 index cc176971327..00000000000 --- a/erpnext/patches/v4_0/fields_to_be_renamed.py +++ /dev/null @@ -1,109 +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.model.utils.rename_field import rename_field -from frappe.modules import scrub, get_doctype_module - -rename_map = { - "Quotation Item": [ - ["ref_rate", "price_list_rate"], - ["base_ref_rate", "base_price_list_rate"], - ["adj_rate", "discount_percentage"], - ["export_rate", "rate"], - ["basic_rate", "base_rate"], - ["amount", "base_amount"], - ["export_amount", "amount"] - ], - - "Sales Order Item": [ - ["ref_rate", "price_list_rate"], - ["base_ref_rate", "base_price_list_rate"], - ["adj_rate", "discount_percentage"], - ["export_rate", "rate"], - ["basic_rate", "base_rate"], - ["amount", "base_amount"], - ["export_amount", "amount"], - ["reserved_warehouse", "warehouse"] - ], - - "Delivery Note Item": [ - ["ref_rate", "price_list_rate"], - ["base_ref_rate", "base_price_list_rate"], - ["adj_rate", "discount_percentage"], - ["export_rate", "rate"], - ["basic_rate", "base_rate"], - ["amount", "base_amount"], - ["export_amount", "amount"] - ], - - "Sales Invoice Item": [ - ["ref_rate", "price_list_rate"], - ["base_ref_rate", "base_price_list_rate"], - ["adj_rate", "discount_percentage"], - ["export_rate", "rate"], - ["basic_rate", "base_rate"], - ["amount", "base_amount"], - ["export_amount", "amount"] - ], - - "Supplier Quotation Item": [ - ["import_ref_rate", "price_list_rate"], - ["purchase_ref_rate", "base_price_list_rate"], - ["discount_rate", "discount_percentage"], - ["import_rate", "rate"], - ["purchase_rate", "base_rate"], - ["amount", "base_amount"], - ["import_amount", "amount"] - ], - - "Purchase Order Item": [ - ["import_ref_rate", "price_list_rate"], - ["purchase_ref_rate", "base_price_list_rate"], - ["discount_rate", "discount_percentage"], - ["import_rate", "rate"], - ["purchase_rate", "base_rate"], - ["amount", "base_amount"], - ["import_amount", "amount"] - ], - - "Purchase Receipt Item": [ - ["import_ref_rate", "price_list_rate"], - ["purchase_ref_rate", "base_price_list_rate"], - ["discount_rate", "discount_percentage"], - ["import_rate", "rate"], - ["purchase_rate", "base_rate"], - ["amount", "base_amount"], - ["import_amount", "amount"] - ], - - "Purchase Invoice Item": [ - ["import_ref_rate", "price_list_rate"], - ["purchase_ref_rate", "base_price_list_rate"], - ["discount_rate", "discount_percentage"], - ["import_rate", "rate"], - ["rate", "base_rate"], - ["amount", "base_amount"], - ["import_amount", "amount"], - ["expense_head", "expense_account"] - ], - - "Item": [ - ["purchase_account", "expense_account"], - ["default_sales_cost_center", "selling_cost_center"], - ["cost_center", "buying_cost_center"], - ["default_income_account", "income_account"], - ], - "Item Price": [ - ["ref_rate", "price_list_rate"] - ] -} - -def execute(): - for dn in rename_map: - frappe.reload_doc(get_doctype_module(dn), "doctype", scrub(dn)) - - for dt, field_list in rename_map.items(): - for field in field_list: - rename_field(dt, field[0], field[1]) diff --git a/erpnext/patches/v4_0/fix_address_template.py b/erpnext/patches/v4_0/fix_address_template.py deleted file mode 100644 index 905e3db3e87..00000000000 --- a/erpnext/patches/v4_0/fix_address_template.py +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors - -from __future__ import unicode_literals -import frappe - -def execute(): - missing_line = """{{ address_line1 }}
    """ - for name, template in frappe.db.sql("select name, template from `tabAddress Template`"): - if missing_line not in template: - d = frappe.get_doc("Address Template", name) - d.template = missing_line + d.template - d.save() diff --git a/erpnext/patches/v4_0/fix_case_of_hr_module_def.py b/erpnext/patches/v4_0/fix_case_of_hr_module_def.py deleted file mode 100644 index e77b427b77e..00000000000 --- a/erpnext/patches/v4_0/fix_case_of_hr_module_def.py +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors - -from __future__ import unicode_literals -import frappe - -def execute(): - hr = frappe.db.get_value("Module Def", "HR") - if hr == "Hr": - frappe.rename_doc("Module Def", "Hr", "HR") - frappe.db.set_value("Module Def", "HR", "module_name", "HR") - - frappe.clear_cache() - frappe.setup_module_map() diff --git a/erpnext/patches/v4_0/fix_contact_address.py b/erpnext/patches/v4_0/fix_contact_address.py deleted file mode 100644 index 6a3e106b8cc..00000000000 --- a/erpnext/patches/v4_0/fix_contact_address.py +++ /dev/null @@ -1,13 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doc("website", "doctype", "contact_us_settings") - address = frappe.db.get_value("Contact Us Settings", None, "address") - if address: - address = frappe.get_doc("Address", address) - contact = frappe.get_doc("Contact Us Settings", "Contact Us Settings") - for f in ("address_title", "address_line1", "address_line2", "city", "state", "country", "pincode"): - contact.set(f, address.get(f)) - - contact.save() \ No newline at end of file diff --git a/erpnext/patches/v4_0/fix_employee_user_id.py b/erpnext/patches/v4_0/fix_employee_user_id.py deleted file mode 100644 index 6f449f97bb6..00000000000 --- a/erpnext/patches/v4_0/fix_employee_user_id.py +++ /dev/null @@ -1,23 +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.utils import get_fullname - -def execute(): - for user_id in frappe.db.sql_list("""select distinct user_id from `tabEmployee` - where ifnull(user_id, '')!='' - group by user_id having count(name) > 1"""): - - fullname = get_fullname(user_id) - employee = frappe.db.get_value("Employee", {"employee_name": fullname, "user_id": user_id}) - - if employee: - frappe.db.sql("""update `tabEmployee` set user_id=null - where user_id=%s and name!=%s""", (user_id, employee)) - else: - count = frappe.db.sql("""select count(*) from `tabEmployee` where user_id=%s""", user_id)[0][0] - frappe.db.sql("""update `tabEmployee` set user_id=null - where user_id=%s limit %s""", (user_id, count - 1)) diff --git a/erpnext/patches/v4_0/global_defaults_to_system_settings.py b/erpnext/patches/v4_0/global_defaults_to_system_settings.py deleted file mode 100644 index 2905fe1e6a9..00000000000 --- a/erpnext/patches/v4_0/global_defaults_to_system_settings.py +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt - -from __future__ import unicode_literals - -import frappe -from collections import Counter -from frappe.core.doctype.user.user import STANDARD_USERS - -def execute(): - frappe.reload_doc("core", "doctype", "system_settings") - system_settings = frappe.get_doc("System Settings") - - # set values from global_defauls - global_defaults = frappe.db.get_value("Global Defaults", None, - ["time_zone", "date_format", "number_format", "float_precision", "session_expiry"], as_dict=True) - - if global_defaults: - for key, val in global_defaults.items(): - if not system_settings.get(key): - system_settings.set(key, val) - - # language - if not system_settings.get("language"): - # find most common language - lang = frappe.db.sql_list("""select language from `tabUser` - where ifnull(language, '')!='' and language not like "Loading%%" and name not in ({standard_users})""".format( - standard_users=", ".join(["%s"]*len(STANDARD_USERS))), tuple(STANDARD_USERS)) - lang = Counter(lang).most_common(1) - lang = (len(lang) > 0) and lang[0][0] or "english" - - system_settings.language = lang - - system_settings.flags.ignore_mandatory = True - system_settings.save() - - global_defaults = frappe.get_doc("Global Defaults") - global_defaults.flags.ignore_mandatory = True - global_defaults.save() diff --git a/erpnext/patches/v4_0/import_country_codes.py b/erpnext/patches/v4_0/import_country_codes.py deleted file mode 100644 index 43e23d5b631..00000000000 --- a/erpnext/patches/v4_0/import_country_codes.py +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt - -from __future__ import unicode_literals -import frappe -from frappe.geo.country_info import get_all -from frappe.utils.install import import_country_and_currency - -from six import iteritems - -def execute(): - frappe.reload_doc("setup", "doctype", "country") - import_country_and_currency() - for name, country in iteritems(get_all()): - frappe.set_value("Country", name, "code", country.get("code")) \ No newline at end of file diff --git a/erpnext/patches/v4_0/map_charge_to_taxes_and_charges.py b/erpnext/patches/v4_0/map_charge_to_taxes_and_charges.py deleted file mode 100644 index 97e217aa054..00000000000 --- a/erpnext/patches/v4_0/map_charge_to_taxes_and_charges.py +++ /dev/null @@ -1,16 +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 - -def execute(): - # update sales cycle - for d in ['Sales Invoice', 'Sales Order', 'Quotation', 'Delivery Note']: - frappe.db.sql("""update `tab%s` set taxes_and_charges=charge""" % d) - - # update purchase cycle - for d in ['Purchase Invoice', 'Purchase Order', 'Supplier Quotation', 'Purchase Receipt']: - frappe.db.sql("""update `tab%s` set taxes_and_charges=purchase_other_charges""" % d) - - frappe.db.sql("""update `tabPurchase Taxes and Charges` set parentfield='other_charges'""") diff --git a/erpnext/patches/v4_0/move_warehouse_user_to_restrictions.py b/erpnext/patches/v4_0/move_warehouse_user_to_restrictions.py deleted file mode 100644 index 8b81936d8d4..00000000000 --- a/erpnext/patches/v4_0/move_warehouse_user_to_restrictions.py +++ /dev/null @@ -1,13 +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 -import frappe.permissions - -def execute(): - for warehouse, user in frappe.db.sql("""select parent, user from `tabWarehouse User`"""): - frappe.permissions.add_user_permission("Warehouse", warehouse, user) - - frappe.delete_doc_if_exists("DocType", "Warehouse User") - frappe.reload_doc("stock", "doctype", "warehouse") diff --git a/erpnext/patches/v4_0/new_address_template.py b/erpnext/patches/v4_0/new_address_template.py deleted file mode 100644 index fa6602706e9..00000000000 --- a/erpnext/patches/v4_0/new_address_template.py +++ /dev/null @@ -1,14 +0,0 @@ -from __future__ import print_function, unicode_literals -import frappe - -def execute(): - frappe.reload_doc("utilities", "doctype", "address_template") - if not frappe.db.sql("select name from `tabAddress Template`"): - try: - d = frappe.new_doc("Address Template") - d.update({"country":frappe.db.get_default("country") or - frappe.db.get_value("Global Defaults", "Global Defaults", "country")}) - d.insert() - except: - print(frappe.get_traceback()) - diff --git a/erpnext/patches/v4_0/reload_sales_print_format.py b/erpnext/patches/v4_0/reload_sales_print_format.py deleted file mode 100644 index b8f090f9f3d..00000000000 --- a/erpnext/patches/v4_0/reload_sales_print_format.py +++ /dev/null @@ -1,8 +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 - -def execute(): - frappe.reload_doc('accounts', 'Print Format', 'POS Invoice') diff --git a/erpnext/patches/v4_0/remove_employee_role_if_no_employee.py b/erpnext/patches/v4_0/remove_employee_role_if_no_employee.py deleted file mode 100644 index 8766ace54f3..00000000000 --- a/erpnext/patches/v4_0/remove_employee_role_if_no_employee.py +++ /dev/null @@ -1,18 +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 -import frappe.permissions - -def execute(): - for user in frappe.db.sql_list("select distinct parent from `tabHas Role` where role='Employee'"): - # if employee record does not exists, remove employee role! - if not frappe.db.get_value("Employee", {"user_id": user}): - try: - user = frappe.get_doc("User", user) - for role in user.get("roles", {"role": "Employee"}): - user.get("roles").remove(role) - user.save() - except frappe.DoesNotExistError: - pass diff --git a/erpnext/patches/v4_0/remove_module_home_pages.py b/erpnext/patches/v4_0/remove_module_home_pages.py deleted file mode 100644 index a2720e0ebf7..00000000000 --- a/erpnext/patches/v4_0/remove_module_home_pages.py +++ /dev/null @@ -1,10 +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 - -def execute(): - for page in ("accounts-home", "website-home", "support-home", "stock-home", "selling-home", "projects-home", - "manufacturing-home", "hr-home", "buying-home"): - frappe.delete_doc("Page", page) \ No newline at end of file diff --git a/erpnext/patches/v4_0/rename_sitemap_to_route.py b/erpnext/patches/v4_0/rename_sitemap_to_route.py deleted file mode 100644 index ffb1fda1440..00000000000 --- a/erpnext/patches/v4_0/rename_sitemap_to_route.py +++ /dev/null @@ -1,17 +0,0 @@ -from __future__ import unicode_literals -import frappe -import frappe.model - -def execute(): - frappe.reload_doc("setup", "doctype", "item_group") - frappe.reload_doc("stock", "doctype", "item") - frappe.reload_doc("setup", "doctype", "sales_partner") - - try: - frappe.model.rename_field("Item Group", "parent_website_sitemap", "parent_website_route") - frappe.model.rename_field("Item", "parent_website_sitemap", "parent_website_route") - frappe.model.rename_field("Sales Partner", "parent_website_sitemap", - "parent_website_route") - except Exception as e: - if e.args[0]!=1054: - raise diff --git a/erpnext/patches/v4_0/reset_permissions_for_masters.py b/erpnext/patches/v4_0/reset_permissions_for_masters.py deleted file mode 100644 index bc1b438e2bb..00000000000 --- a/erpnext/patches/v4_0/reset_permissions_for_masters.py +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import print_function, unicode_literals -from frappe.permissions import reset_perms - -def execute(): - for doctype in ("About Us Settings", "Accounts Settings", "Activity Type", - "Blog Category", "Blog Settings", "Blogger", "Branch", "Brand", "Buying Settings", - "Communication", "Company", "Contact Us Settings", - "Country", "Currency", "Currency Exchange", "Deduction Type", "Department", - "Designation", "Earning Type", "Event", "Feed", "File", "Fiscal Year", - "HR Settings", "Industry Type", "Leave Type", "Letter Head", - "Mode of Payment", "Module Def", "Naming Series", "POS Setting", "Print Heading", - "Report", "Role", "Selling Settings", "Stock Settings", "Supplier Type", "UOM"): - try: - reset_perms(doctype) - except: - print("Error resetting perms for", doctype) - raise diff --git a/erpnext/patches/v4_0/save_default_letterhead.py b/erpnext/patches/v4_0/save_default_letterhead.py deleted file mode 100644 index 5d75f096b3a..00000000000 --- a/erpnext/patches/v4_0/save_default_letterhead.py +++ /dev/null @@ -1,13 +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 - -def execute(): - """save default letterhead to set default_letter_head_content""" - try: - letter_head = frappe.get_doc("Letter Head", {"is_default": 1}) - letter_head.save() - except frappe.DoesNotExistError: - pass diff --git a/erpnext/patches/v4_0/set_pricing_rule_for_buying_or_selling.py b/erpnext/patches/v4_0/set_pricing_rule_for_buying_or_selling.py deleted file mode 100644 index 7e472e21953..00000000000 --- a/erpnext/patches/v4_0/set_pricing_rule_for_buying_or_selling.py +++ /dev/null @@ -1,13 +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 - -def execute(): - frappe.reload_doc("accounts", "doctype", "pricing_rule") - frappe.db.sql("""update `tabPricing Rule` set selling=1 where ifnull(applicable_for, '') in - ('', 'Customer', 'Customer Group', 'Territory', 'Sales Partner', 'Campaign')""") - - frappe.db.sql("""update `tabPricing Rule` set buying=1 where ifnull(applicable_for, '') in - ('', 'Supplier', 'Supplier Type')""") diff --git a/erpnext/patches/v4_0/split_email_settings.py b/erpnext/patches/v4_0/split_email_settings.py deleted file mode 100644 index 5d1dea60ee0..00000000000 --- a/erpnext/patches/v4_0/split_email_settings.py +++ /dev/null @@ -1,67 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import print_function, unicode_literals -import frappe - -def execute(): - print("WARNING!!!! Email Settings not migrated. Please setup your email again.") - - # this will happen if you are migrating very old accounts - # comment out this line below and remember to create new Email Accounts - # for incoming and outgoing mails - raise Exception - - return - - - frappe.reload_doc("core", "doctype", "outgoing_email_settings") - frappe.reload_doc("support", "doctype", "support_email_settings") - - email_settings = get_email_settings() - map_outgoing_email_settings(email_settings) - map_support_email_settings(email_settings) - - -def map_outgoing_email_settings(email_settings): - outgoing_email_settings = frappe.get_doc("Outgoing Email Settings") - for fieldname in (("outgoing_mail_server", "mail_server"), - "use_ssl", "mail_port", "mail_login", "mail_password", - "always_use_login_id_as_sender", "auto_email_id"): - - if isinstance(fieldname, tuple): - from_fieldname, to_fieldname = fieldname - else: - from_fieldname = to_fieldname = fieldname - - outgoing_email_settings.set(to_fieldname, email_settings.get(from_fieldname)) - - outgoing_email_settings._fix_numeric_types() - outgoing_email_settings.save() - -def map_support_email_settings(email_settings): - support_email_settings = frappe.get_doc("Support Email Settings") - - for fieldname in ("sync_support_mails", "support_email", - ("support_host", "mail_server"), - ("support_use_ssl", "use_ssl"), - ("support_username", "mail_login"), - ("support_password", "mail_password"), - "support_signature", "send_autoreply", "support_autoreply"): - - if isinstance(fieldname, tuple): - from_fieldname, to_fieldname = fieldname - else: - from_fieldname = to_fieldname = fieldname - - support_email_settings.set(to_fieldname, email_settings.get(from_fieldname)) - - support_email_settings._fix_numeric_types() - support_email_settings.save() - -def get_email_settings(): - ret = {} - for field, value in frappe.db.sql("select field, value from tabSingles where doctype='Email Settings'"): - ret[field] = value - return ret - diff --git a/erpnext/patches/v4_0/update_account_root_type.py b/erpnext/patches/v4_0/update_account_root_type.py deleted file mode 100644 index 15ddf032a4a..00000000000 --- a/erpnext/patches/v4_0/update_account_root_type.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import print_function, unicode_literals -import frappe - -def execute(): - frappe.reload_doc("accounts", "doctype", "account") - - account_table_columns = frappe.db.get_table_columns("Account") - if "debit_or_credit" in account_table_columns and "is_pl_account" in account_table_columns: - frappe.db.sql("""UPDATE tabAccount - SET root_type = CASE - WHEN (debit_or_credit='Debit' and is_pl_account = 'No') THEN 'Asset' - WHEN (debit_or_credit='Credit' and is_pl_account = 'No') THEN 'Liability' - WHEN (debit_or_credit='Debit' and is_pl_account = 'Yes') THEN 'Expense' - WHEN (debit_or_credit='Credit' and is_pl_account = 'Yes') THEN 'Income' - END - WHERE ifnull(parent_account, '') = '' - """) - - else: - for key, root_type in (("asset", "Asset"), ("liabilities", "Liability"), ("expense", "Expense"), - ("income", "Income")): - frappe.db.sql("""update tabAccount set root_type=%s where name like %s - and ifnull(parent_account, '')=''""", (root_type, "%" + key + "%")) - - for root in frappe.db.sql("""SELECT name, lft, rgt, root_type FROM `tabAccount` - WHERE ifnull(parent_account, '')=''""", as_dict=True): - if root.root_type: - frappe.db.sql("""UPDATE tabAccount SET root_type=%s WHERE lft>%s and rgt<%s""", - (root.root_type, root.lft, root.rgt)) - else: - print(b"Root type not found for {0}".format(root.name.encode("utf-8"))) diff --git a/erpnext/patches/v4_0/update_custom_print_formats_for_renamed_fields.py b/erpnext/patches/v4_0/update_custom_print_formats_for_renamed_fields.py deleted file mode 100644 index d784a1b1828..00000000000 --- a/erpnext/patches/v4_0/update_custom_print_formats_for_renamed_fields.py +++ /dev/null @@ -1,36 +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 -import re - -def execute(): - # NOTE: sequence is important - fields_list = ( - ("amount", "base_amount"), - ("ref_rate", "price_list_rate"), - ("base_ref_rate", "base_price_list_rate"), - ("adj_rate", "discount_percentage"), - ("export_rate", "rate"), - ("basic_rate", "base_rate"), - ("export_amount", "amount"), - ("reserved_warehouse", "warehouse"), - ("import_ref_rate", "price_list_rate"), - ("purchase_ref_rate", "base_price_list_rate"), - ("discount_rate", "discount_percentage"), - ("import_rate", "rate"), - ("purchase_rate", "base_rate"), - ("import_amount", "amount") - ) - - condition = " or ".join("""html like "%%{}%%" """.format(d[0].replace("_", "\\_")) for d in fields_list - if d[0] != "amount") - - for name, html in frappe.db.sql("""select name, html from `tabPrint Format` - where standard = 'No' and ({}) and html not like '%%frappe.%%'""".format(condition)): - html = html.replace("wn.", "frappe.") - for from_field, to_field in fields_list: - html = re.sub(r"\b{}\b".format(from_field), to_field, html) - - frappe.db.set_value("Print Format", name, "html", html) diff --git a/erpnext/patches/v4_0/update_incharge_name_to_sales_person_in_maintenance_schedule.py b/erpnext/patches/v4_0/update_incharge_name_to_sales_person_in_maintenance_schedule.py deleted file mode 100644 index fe66a5e3ef9..00000000000 --- a/erpnext/patches/v4_0/update_incharge_name_to_sales_person_in_maintenance_schedule.py +++ /dev/null @@ -1,12 +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 - -def execute(): - frappe.reload_doc("support", "doctype", "schedules") - frappe.reload_doc("support", "doctype", "maintenance_schedule_item") - - frappe.db.sql("""update `tabMaintenance Schedule Detail` set sales_person=incharge_name""") - frappe.db.sql("""update `tabMaintenance Schedule Item` set sales_person=incharge_name""") \ No newline at end of file diff --git a/erpnext/patches/v4_0/update_other_charges_in_custom_purchase_print_formats.py b/erpnext/patches/v4_0/update_other_charges_in_custom_purchase_print_formats.py deleted file mode 100644 index 2e2e77a9fca..00000000000 --- a/erpnext/patches/v4_0/update_other_charges_in_custom_purchase_print_formats.py +++ /dev/null @@ -1,12 +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 -import re - -def execute(): - for name, html in frappe.db.sql("""select name, html from `tabPrint Format` - where standard = 'No' and html like '%%purchase\\_tax\\_details%%'"""): - html = re.sub(r"\bpurchase_tax_details\b", "taxes", html) - frappe.db.set_value("Print Format", name, "html", html) diff --git a/erpnext/patches/v4_0/update_tax_amount_after_discount.py b/erpnext/patches/v4_0/update_tax_amount_after_discount.py deleted file mode 100644 index d10329ef375..00000000000 --- a/erpnext/patches/v4_0/update_tax_amount_after_discount.py +++ /dev/null @@ -1,20 +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 - -def execute(): - frappe.reload_doc("accounts", "doctype", "sales_taxes_and_charges") - docs_with_discount_amount = frappe._dict() - for dt in ["Quotation", "Sales Order", "Delivery Note", "Sales Invoice"]: - records = frappe.db.sql_list("""select name from `tab%s` - where ifnull(discount_amount, 0) > 0 and docstatus=1""" % dt) - docs_with_discount_amount[dt] = records - - for dt, discounted_records in docs_with_discount_amount.items(): - frappe.db.sql("""update `tabSales Taxes and Charges` - set tax_amount_after_discount_amount = tax_amount - where parenttype = %s and parent not in (%s)""" % - ('%s', ', '.join(['%s']*(len(discounted_records)+1))), - tuple([dt, ''] + discounted_records)) diff --git a/erpnext/patches/v4_0/update_user_properties.py b/erpnext/patches/v4_0/update_user_properties.py deleted file mode 100644 index f2085ce4df6..00000000000 --- a/erpnext/patches/v4_0/update_user_properties.py +++ /dev/null @@ -1,51 +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 -import frappe.permissions -import frappe.defaults - -def execute(): - frappe.reload_doc("core", "doctype", "docfield") - frappe.reload_doc("hr", "doctype", "employee") - - set_print_email_permissions() - migrate_user_properties_to_user_permissions() - - frappe.clear_cache() - -def migrate_user_properties_to_user_permissions(): - for d in frappe.db.sql("""select parent, defkey, defvalue from tabDefaultValue - where parent not in ('__global', '__default')""", as_dict=True): - df = frappe.db.sql("""select options from tabDocField - where fieldname=%s and fieldtype='Link'""", d.defkey, as_dict=True) - - if df: - frappe.db.sql("""update tabDefaultValue - set defkey=%s, parenttype='User Permission' - where defkey=%s and - parent not in ('__global', '__default')""", (df[0].options, d.defkey)) - -def set_print_email_permissions(): - # reset Page perms - from frappe.core.page.permission_manager.permission_manager import reset - reset("Page") - reset("Report") - - if "allow_print" not in frappe.db.get_table_columns("DocType"): - return - - # patch to move print, email into DocPerm - # NOTE: allow_print and allow_email are misnamed. They were used to hide print / hide email - for doctype, hide_print, hide_email in frappe.db.sql("""select name, ifnull(allow_print, 0), ifnull(allow_email, 0) - from `tabDocType` where ifnull(issingle, 0)=0 and ifnull(istable, 0)=0 and - (ifnull(allow_print, 0)=0 or ifnull(allow_email, 0)=0)"""): - - if not hide_print: - frappe.db.sql("""update `tabDocPerm` set `print`=1 - where permlevel=0 and `read`=1 and parent=%s""", doctype) - - if not hide_email: - frappe.db.sql("""update `tabDocPerm` set `email`=1 - where permlevel=0 and `read`=1 and parent=%s""", doctype) diff --git a/erpnext/patches/v4_0/update_users_report_view_settings.py b/erpnext/patches/v4_0/update_users_report_view_settings.py deleted file mode 100644 index 6f216f5b38b..00000000000 --- a/erpnext/patches/v4_0/update_users_report_view_settings.py +++ /dev/null @@ -1,12 +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 - -from frappe.model.utils.rename_field import update_users_report_view_settings -from erpnext.patches.v4_0.fields_to_be_renamed import rename_map - -def execute(): - for dt, field_list in rename_map.items(): - for field in field_list: - update_users_report_view_settings(dt, field[0], field[1]) diff --git a/erpnext/patches/v4_0/validate_v3_patch.py b/erpnext/patches/v4_0/validate_v3_patch.py deleted file mode 100644 index 3df39edea69..00000000000 --- a/erpnext/patches/v4_0/validate_v3_patch.py +++ /dev/null @@ -1,11 +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 - -def execute(): - from frappe.modules.patch_handler import executed - last_v3_patch = 'patches.1401.fix_pos_outstanding' - if not executed(last_v3_patch): - raise Exception("site not ready to migrate to version 4") diff --git a/erpnext/patches/v4_1/__init__.py b/erpnext/patches/v4_1/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/erpnext/patches/v4_1/fix_delivery_and_billing_status.py b/erpnext/patches/v4_1/fix_delivery_and_billing_status.py deleted file mode 100644 index 8cc6a4b0bed..00000000000 --- a/erpnext/patches/v4_1/fix_delivery_and_billing_status.py +++ /dev/null @@ -1,12 +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 - -def execute(): - frappe.db.sql("""update `tabSales Order` set delivery_status = 'Not Delivered' - where delivery_status = 'Delivered' and ifnull(per_delivered, 0) = 0 and ifnull(docstatus, 0) in (0, 1)""") - - frappe.db.sql("""update `tabSales Order` set billing_status = 'Not Billed' - where billing_status = 'Billed' and ifnull(per_billed, 0) = 0 and ifnull(docstatus, 0) in (0, 1)""") diff --git a/erpnext/patches/v4_1/fix_jv_remarks.py b/erpnext/patches/v4_1/fix_jv_remarks.py deleted file mode 100644 index e07bf05f1a5..00000000000 --- a/erpnext/patches/v4_1/fix_jv_remarks.py +++ /dev/null @@ -1,21 +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 - -def execute(): - reference_date = guess_reference_date() - for name in frappe.db.sql_list("""select name from `tabJournal Entry` - where date(creation)>=%s""", reference_date): - jv = frappe.get_doc("Journal Entry", name) - try: - jv.create_remarks() - except frappe.MandatoryError: - pass - else: - frappe.db.set_value("Journal Entry", jv.name, "remark", jv.remark) - -def guess_reference_date(): - return (frappe.db.get_value("Patch Log", {"patch": "erpnext.patches.v4_0.validate_v3_patch"}, "creation") - or "2014-05-06") diff --git a/erpnext/patches/v4_1/fix_sales_order_delivered_status.py b/erpnext/patches/v4_1/fix_sales_order_delivered_status.py deleted file mode 100644 index 66037b8958b..00000000000 --- a/erpnext/patches/v4_1/fix_sales_order_delivered_status.py +++ /dev/null @@ -1,15 +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 - -def execute(): - for si in frappe.db.sql_list("""select name - from `tabSales Invoice` - where ifnull(update_stock,0) = 1 and docstatus = 1 and exists( - select name from `tabSales Invoice Item` where parent=`tabSales Invoice`.name and - ifnull(so_detail, "") != "")"""): - - invoice = frappe.get_doc("Sales Invoice", si) - invoice.update_qty() diff --git a/erpnext/patches/v4_1/set_outgoing_email_footer.py b/erpnext/patches/v4_1/set_outgoing_email_footer.py deleted file mode 100644 index 54d016bf5f6..00000000000 --- a/erpnext/patches/v4_1/set_outgoing_email_footer.py +++ /dev/null @@ -1,12 +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 erpnext.setup.install import default_mail_footer - -def execute(): - return - mail_footer = frappe.db.get_default('mail_footer') or '' - mail_footer += default_mail_footer - frappe.db.set_value("Outgoing Email Settings", "Outgoing Email Settings", "footer", mail_footer) diff --git a/erpnext/patches/v4_2/__init__.py b/erpnext/patches/v4_2/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/erpnext/patches/v4_2/add_currency_turkish_lira.py b/erpnext/patches/v4_2/add_currency_turkish_lira.py deleted file mode 100644 index 1a46089f943..00000000000 --- a/erpnext/patches/v4_2/add_currency_turkish_lira.py +++ /dev/null @@ -1,10 +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 - -def execute(): - return - # country = get_country_info(country="Turkey") - # add_country_and_currency("Turkey", country) diff --git a/erpnext/patches/v4_2/default_website_style.py b/erpnext/patches/v4_2/default_website_style.py deleted file mode 100644 index e8f9502ea62..00000000000 --- a/erpnext/patches/v4_2/default_website_style.py +++ /dev/null @@ -1,11 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - return - # frappe.reload_doc('website', 'doctype', 'style_settings') - # style_settings = frappe.get_doc("Style Settings", "Style Settings") - # if not style_settings.apply_style: - # style_settings.update(default_properties) - # style_settings.apply_style = 1 - # style_settings.save() diff --git a/erpnext/patches/v4_2/delete_gl_entries_for_cancelled_invoices.py b/erpnext/patches/v4_2/delete_gl_entries_for_cancelled_invoices.py deleted file mode 100644 index 169b1e29275..00000000000 --- a/erpnext/patches/v4_2/delete_gl_entries_for_cancelled_invoices.py +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - cancelled_invoices = frappe.db.sql_list("""select name from `tabSales Invoice` - where docstatus = 2 and ifnull(update_stock, 0) = 1""") - - if cancelled_invoices: - frappe.db.sql("""delete from `tabGL Entry` - where voucher_type = 'Sales Invoice' and voucher_no in (%s)""" - % (', '.join(['%s']*len(cancelled_invoices))), tuple(cancelled_invoices)) \ No newline at end of file diff --git a/erpnext/patches/v4_2/delete_old_print_formats.py b/erpnext/patches/v4_2/delete_old_print_formats.py deleted file mode 100644 index cacdb85ce07..00000000000 --- a/erpnext/patches/v4_2/delete_old_print_formats.py +++ /dev/null @@ -1,23 +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 - -def execute(): - old_formats = ("Sales Invoice", "Sales Invoice Spartan", "Sales Invoice Modern", - "Sales Invoice Classic", - "Sales Order Spartan", "Sales Order Modern", "Sales Order Classic", - "Purchase Order Spartan", "Purchase Order Modern", "Purchase Order Classic", - "Quotation Spartan", "Quotation Modern", "Quotation Classic", - "Delivery Note Spartan", "Delivery Note Modern", "Delivery Note Classic") - - for fmt in old_formats: - # update property setter - for ps in frappe.db.sql_list("""select name from `tabProperty Setter` - where property='default_print_format' and value=%s""", fmt): - ps = frappe.get_doc("Property Setter", ps) - ps.value = "Standard" - ps.save(ignore_permissions = True) - - frappe.delete_doc_if_exists("Print Format", fmt) diff --git a/erpnext/patches/v4_2/discount_amount.py b/erpnext/patches/v4_2/discount_amount.py deleted file mode 100644 index 7ab61bdbeaa..00000000000 --- a/erpnext/patches/v4_2/discount_amount.py +++ /dev/null @@ -1,12 +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.modules import scrub, get_doctype_module - -def execute(): - for dt in ["Quotation", "Sales Order", "Delivery Note", "Sales Invoice"]: - frappe.reload_doc(get_doctype_module(dt), "doctype", scrub(dt)) - frappe.db.sql("""update `tab{0}` set base_discount_amount=discount_amount, - discount_amount=discount_amount/conversion_rate""".format(dt)) diff --git a/erpnext/patches/v4_2/fix_account_master_type.py b/erpnext/patches/v4_2/fix_account_master_type.py deleted file mode 100644 index 99444ce83b2..00000000000 --- a/erpnext/patches/v4_2/fix_account_master_type.py +++ /dev/null @@ -1,12 +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 - -def execute(): - for d in frappe.db.sql("""select name from `tabAccount` - where ifnull(master_type, '') not in ('Customer', 'Supplier', 'Employee', '') and docstatus=0"""): - ac = frappe.get_doc("Account", d[0]) - ac.master_type = None - ac.save() diff --git a/erpnext/patches/v4_2/fix_gl_entries_for_stock_transactions.py b/erpnext/patches/v4_2/fix_gl_entries_for_stock_transactions.py deleted file mode 100644 index c6c94d41797..00000000000 --- a/erpnext/patches/v4_2/fix_gl_entries_for_stock_transactions.py +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import print_function, unicode_literals -import frappe -from frappe.utils import flt - -def execute(): - from erpnext.stock.stock_balance import repost - repost(allow_zero_rate=True, only_actual=True) - - frappe.reload_doctype("Account") - - warehouse_account = frappe.db.sql("""select name, master_name from tabAccount - where ifnull(account_type, '') = 'Warehouse'""") - if warehouse_account: - warehouses = [d[1] for d in warehouse_account] - accounts = [d[0] for d in warehouse_account] - - stock_vouchers = frappe.db.sql("""select distinct sle.voucher_type, sle.voucher_no - from `tabStock Ledger Entry` sle - where sle.warehouse in (%s) - order by sle.posting_date""" % - ', '.join(['%s']*len(warehouses)), tuple(warehouses)) - - rejected = [] - for voucher_type, voucher_no in stock_vouchers: - stock_bal = frappe.db.sql("""select sum(stock_value_difference) from `tabStock Ledger Entry` - where voucher_type=%s and voucher_no =%s and warehouse in (%s)""" % - ('%s', '%s', ', '.join(['%s']*len(warehouses))), tuple([voucher_type, voucher_no] + warehouses)) - - account_bal = frappe.db.sql("""select ifnull(sum(ifnull(debit, 0) - ifnull(credit, 0)), 0) - from `tabGL Entry` - where voucher_type=%s and voucher_no =%s and account in (%s) - group by voucher_type, voucher_no""" % - ('%s', '%s', ', '.join(['%s']*len(accounts))), tuple([voucher_type, voucher_no] + accounts)) - - if stock_bal and account_bal and abs(flt(stock_bal[0][0]) - flt(account_bal[0][0])) > 0.1: - try: - print(voucher_type, voucher_no, stock_bal[0][0], account_bal[0][0]) - - frappe.db.sql("""delete from `tabGL Entry` - where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no)) - - voucher = frappe.get_doc(voucher_type, voucher_no) - voucher.make_gl_entries() - frappe.db.commit() - except Exception as e: - print(frappe.get_traceback()) - rejected.append([voucher_type, voucher_no]) - frappe.db.rollback() - - print("Failed to repost: ") - print(rejected) diff --git a/erpnext/patches/v4_2/fix_recurring_orders.py b/erpnext/patches/v4_2/fix_recurring_orders.py deleted file mode 100644 index ea1724a0401..00000000000 --- a/erpnext/patches/v4_2/fix_recurring_orders.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - sales_orders = frappe.db.sql("""select name from `tabSales Order` - where docstatus = 1 and ifnull(is_recurring, 0) = 1 - and (per_delivered > 0 or per_billed > 0)""", as_dict=1) - - for so in sales_orders: - if not frappe.db.exists("Delivery Note Item", {"against_sales_order": so.name, "docstatus": 1}): - frappe.db.sql("""update `tabSales Order` set per_delivered = 0, - delivery_status = 'Not Delivered' where name = %s""", so.name) - frappe.db.sql("""update `tabSales Order Item` set delivered_qty = 0 - where parent = %s""", so.name) - - if not frappe.db.exists("Sales Invoice Item", {"sales_order": so.name, "docstatus": 1}): - frappe.db.sql("""update `tabSales Order` set per_billed = 0, - billing_status = 'Not Billed' where name = %s""", so.name) - frappe.db.sql("""update `tabSales Order Item` set billed_amt = 0 - where parent = %s""", so.name) - - purchase_orders = frappe.db.sql("""select name from `tabPurchase Order` - where docstatus = 1 and ifnull(is_recurring, 0) = 1 - and (per_received > 0 or per_billed > 0)""", as_dict=1) - - for po in purchase_orders: - if not frappe.db.exists("Purchase Receipt Item", {"prevdoc_doctype": "Purchase Order", - "prevdoc_docname": po.name, "docstatus": 1}): - frappe.db.sql("""update `tabPurchase Order` set per_received = 0 - where name = %s""", po.name) - frappe.db.sql("""update `tabPurchase Order Item` set received_qty = 0 - where parent = %s""", po.name) - - if not frappe.db.exists("Purchase Invoice Item", {"purchase_order": po.name, "docstatus": 1}): - frappe.db.sql("""update `tabPurchase Order` set per_billed = 0 - where name = %s""", po.name) - frappe.db.sql("""update `tabPurchase Order Item` set billed_amt = 0 - where parent = %s""", po.name) \ No newline at end of file diff --git a/erpnext/patches/v4_2/party_model.py b/erpnext/patches/v4_2/party_model.py deleted file mode 100644 index 46d7fffee10..00000000000 --- a/erpnext/patches/v4_2/party_model.py +++ /dev/null @@ -1,117 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import print_function, unicode_literals -import frappe - -def execute(): - frappe.reload_doc("accounts", "doctype", "account") - frappe.reload_doc("setup", "doctype", "company") - frappe.reload_doc("accounts", "doctype", "gl_entry") - frappe.reload_doc("accounts", "doctype", "journal_entry_account") - receivable_payable_accounts = create_receivable_payable_account() - if receivable_payable_accounts: - set_party_in_jv_and_gl_entry(receivable_payable_accounts) - delete_individual_party_account() - remove_customer_supplier_account_report() - -def create_receivable_payable_account(): - receivable_payable_accounts = frappe._dict() - - def _create_account(args): - if args["parent_account"] and frappe.db.exists("Account", args["parent_account"]): - account_id = frappe.db.get_value("Account", - {"account_name": args["account_name"], "company": args["company"]}) - if not account_id: - account = frappe.new_doc("Account") - account.is_group = 0 - account.update(args) - account.insert() - - account_id = account.name - - frappe.db.set_value("Company", args["company"], ("default_receivable_account" - if args["account_type"]=="Receivable" else "default_payable_account"), account_id) - - receivable_payable_accounts.setdefault(args["company"], {}).setdefault(args["account_type"], account_id) - - for company in frappe.db.sql_list("select name from tabCompany"): - _create_account({ - "account_name": "Debtors", - "account_type": "Receivable", - "company": company, - "parent_account": get_parent_account(company, "Customer") - }) - - _create_account({ - "account_name": "Creditors", - "account_type": "Payable", - "company": company, - "parent_account": get_parent_account(company, "Supplier") - }) - - return receivable_payable_accounts - -def get_parent_account(company, master_type): - parent_account = None - - if "receivables_group" in frappe.db.get_table_columns("Company"): - parent_account = frappe.get_cached_value('Company', company, - "receivables_group" if master_type=="Customer" else "payables_group") - if not parent_account: - parent_account = frappe.db.get_value("Account", {"company": company, - "account_name": "Accounts Receivable" if master_type=="Customer" else "Accounts Payable"}) - - if not parent_account: - parent_account = frappe.db.sql_list("""select parent_account from tabAccount - where company=%s and ifnull(master_type, '')=%s and ifnull(master_name, '')!='' limit 1""", - (company, master_type)) - parent_account = parent_account[0][0] if parent_account else None - - return parent_account - -def set_party_in_jv_and_gl_entry(receivable_payable_accounts): - accounts = frappe.db.sql("""select name, master_type, master_name, company from `tabAccount` - where ifnull(master_type, '') in ('Customer', 'Supplier') and ifnull(master_name, '') != ''""", as_dict=1) - - account_map = frappe._dict() - for d in accounts: - account_map.setdefault(d.name, d) - - if not account_map: - return - - for dt in ["Journal Entry Account", "GL Entry"]: - records = frappe.db.sql("""select name, account from `tab%s` - where account in (%s) and ifnull(party, '') = '' and docstatus < 2""" % - (dt, ", ".join(['%s']*len(account_map))), tuple(account_map.keys()), as_dict=1) - for i, d in enumerate(records): - account_details = account_map.get(d.account, {}) - account_type = "Receivable" if account_details.get("master_type")=="Customer" else "Payable" - new_account = receivable_payable_accounts[account_details.get("company")][account_type] - - frappe.db.sql("update `tab{0}` set account=%s, party_type=%s, party=%s where name=%s".format(dt), - (new_account, account_details.get("master_type"), account_details.get("master_name"), d.name)) - - if i%500 == 0: - frappe.db.commit() - -def delete_individual_party_account(): - frappe.db.sql("""delete from `tabAccount` - where ifnull(master_type, '') in ('Customer', 'Supplier') - and ifnull(master_name, '') != '' - and not exists(select gle.name from `tabGL Entry` gle - where gle.account = tabAccount.name)""") - - accounts_not_deleted = frappe.db.sql_list("""select tabAccount.name from `tabAccount` - where ifnull(master_type, '') in ('Customer', 'Supplier') - and ifnull(master_name, '') != '' - and exists(select gle.name from `tabGL Entry` gle where gle.account = tabAccount.name)""") - - if accounts_not_deleted: - print("Accounts not deleted: " + "\n".join(accounts_not_deleted)) - - -def remove_customer_supplier_account_report(): - for d in ["Customer Account Head", "Supplier Account Head"]: - frappe.delete_doc("Report", d) diff --git a/erpnext/patches/v4_2/recalculate_bom_cost.py b/erpnext/patches/v4_2/recalculate_bom_cost.py deleted file mode 100644 index eee89fce96b..00000000000 --- a/erpnext/patches/v4_2/recalculate_bom_cost.py +++ /dev/null @@ -1,16 +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 - -def execute(): - for d in frappe.db.sql("select name from `tabBOM` where docstatus < 2"): - try: - document = frappe.get_doc('BOM', d[0]) - if document.docstatus == 1: - document.flags.ignore_validate_update_after_submit = True - document.calculate_cost() - document.save() - except: - pass diff --git a/erpnext/patches/v4_2/repost_sle_for_si_with_no_warehouse.py b/erpnext/patches/v4_2/repost_sle_for_si_with_no_warehouse.py deleted file mode 100644 index 1356129dc0a..00000000000 --- a/erpnext/patches/v4_2/repost_sle_for_si_with_no_warehouse.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import print_function, unicode_literals -import frappe -from erpnext.stock.stock_ledger import NegativeStockError - -def execute(): - si_list = frappe.db.sql("""select distinct si.name - from `tabSales Invoice Item` si_item, `tabSales Invoice` si - where si.name = si_item.parent and si.modified > '2015-02-16' and si.docstatus=1 - and ifnull(si_item.warehouse, '') = '' and ifnull(si.update_stock, 0) = 1 - order by posting_date, posting_time""", as_dict=1) - - failed_list = [] - for si in si_list: - try: - si_doc = frappe.get_doc("Sales Invoice", si.name) - si_doc.docstatus = 2 - si_doc.on_cancel() - - si_doc.docstatus = 1 - si_doc.set_missing_item_details() - si_doc.on_submit() - frappe.db.commit() - except: - failed_list.append(si.name) - frappe.local.stockledger_exceptions = None - frappe.db.rollback() - - print("Failed to repost: ", failed_list) - - - \ No newline at end of file diff --git a/erpnext/patches/v4_2/repost_stock_reconciliation.py b/erpnext/patches/v4_2/repost_stock_reconciliation.py deleted file mode 100644 index ad20ebbae41..00000000000 --- a/erpnext/patches/v4_2/repost_stock_reconciliation.py +++ /dev/null @@ -1,31 +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 -import json - -def execute(): - existing_allow_negative_stock = frappe.db.get_value("Stock Settings", None, "allow_negative_stock") - frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1) - - head_row = ["Item Code", "Warehouse", "Quantity", "Valuation Rate"] - stock_reco_to_be_reposted = [] - for d in frappe.db.sql("""select name, reconciliation_json from `tabStock Reconciliation` - where docstatus=1 and creation > '2014-03-01'""", as_dict=1): - data = json.loads(d.reconciliation_json) - for row in data[data.index(head_row)+1:]: - if row[3] in ["", None]: - stock_reco_to_be_reposted.append(d.name) - break - - for dn in stock_reco_to_be_reposted: - reco = frappe.get_doc("Stock Reconciliation", dn) - reco.docstatus = 2 - reco.on_cancel() - - reco.docstatus = 1 - reco.validate() - reco.on_submit() - - frappe.db.set_value("Stock Settings", None, "allow_negative_stock", existing_allow_negative_stock) diff --git a/erpnext/patches/v4_2/reset_bom_costs.py b/erpnext/patches/v4_2/reset_bom_costs.py deleted file mode 100644 index 42ca7594678..00000000000 --- a/erpnext/patches/v4_2/reset_bom_costs.py +++ /dev/null @@ -1,17 +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 - -def execute(): - frappe.reload_doc('manufacturing', 'doctype', 'bom_operation') - for d in frappe.db.sql("""select name from `tabBOM` where docstatus < 2""", as_dict=1): - try: - bom = frappe.get_doc('BOM', d.name) - bom.flags.ignore_validate_update_after_submit = True - bom.calculate_cost() - bom.save() - frappe.db.commit() - except: - frappe.db.rollback() diff --git a/erpnext/patches/v4_2/seprate_manufacture_and_repack.py b/erpnext/patches/v4_2/seprate_manufacture_and_repack.py deleted file mode 100644 index 2c935436a2c..00000000000 --- a/erpnext/patches/v4_2/seprate_manufacture_and_repack.py +++ /dev/null @@ -1,9 +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 - -def execute(): - frappe.db.sql("""update `tabStock Entry` set purpose='Manufacture' where purpose='Manufacture/Repack' and ifnull(work_order,"")!="" """) - frappe.db.sql("""update `tabStock Entry` set purpose='Repack' where purpose='Manufacture/Repack' and ifnull(work_order,"")="" """) \ No newline at end of file diff --git a/erpnext/patches/v4_2/set_company_country.py b/erpnext/patches/v4_2/set_company_country.py deleted file mode 100644 index 89f07f28731..00000000000 --- a/erpnext/patches/v4_2/set_company_country.py +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import print_function, unicode_literals -import frappe - -def execute(): - country = frappe.db.get_single_value("Global Defaults", "country") - if not country: - print("Country not specified in Global Defaults") - return - - for company in frappe.db.sql_list("""select name from `tabCompany` - where ifnull(country, '')=''"""): - frappe.db.set_value("Company", company, "country", country) diff --git a/erpnext/patches/v4_2/set_item_has_batch.py b/erpnext/patches/v4_2/set_item_has_batch.py deleted file mode 100644 index 7e52d2def0f..00000000000 --- a/erpnext/patches/v4_2/set_item_has_batch.py +++ /dev/null @@ -1,65 +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 - -def execute(): - frappe.db.sql("update tabItem set has_batch_no = 0 where ifnull(has_batch_no, '') = ''") - frappe.db.sql("update tabItem set has_serial_no = 0 where ifnull(has_serial_no, '') = ''") - - item_list = frappe.db.sql("""select name, has_batch_no, has_serial_no from tabItem - where is_stock_item = 1""", as_dict=1) - - sle_count = get_sle_count() - sle_with_batch = get_sle_with_batch() - sle_with_serial = get_sle_with_serial() - - batch_items = get_items_with_batch() - serialized_items = get_items_with_serial() - - for d in item_list: - if d.has_batch_no == 1: - if d.name not in batch_items and sle_count.get(d.name) and sle_count.get(d.name) != sle_with_batch.get(d.name): - frappe.db.set_value("Item", d.name, "has_batch_no", 0) - else: - if d.name in batch_items or (sle_count.get(d.name) and sle_count.get(d.name) == sle_with_batch.get(d.name)): - frappe.db.set_value("Item", d.name, "has_batch_no", 1) - - if d.has_serial_no == 1: - if d.name not in serialized_items and sle_count.get(d.name) and sle_count.get(d.name) != sle_with_serial.get(d.name): - frappe.db.set_value("Item", d.name, "has_serial_no", 0) - else: - if d.name in serialized_items or (sle_count.get(d.name) and sle_count.get(d.name) == sle_with_serial.get(d.name)): - frappe.db.set_value("Item", d.name, "has_serial_no", 1) - - -def get_sle_count(): - sle_count = {} - for d in frappe.db.sql("""select item_code, count(name) as cnt from `tabStock Ledger Entry` group by item_code""", as_dict=1): - sle_count.setdefault(d.item_code, d.cnt) - - return sle_count - -def get_sle_with_batch(): - sle_with_batch = {} - for d in frappe.db.sql("""select item_code, count(name) as cnt from `tabStock Ledger Entry` - where ifnull(batch_no, '') != '' group by item_code""", as_dict=1): - sle_with_batch.setdefault(d.item_code, d.cnt) - - return sle_with_batch - - -def get_sle_with_serial(): - sle_with_serial = {} - for d in frappe.db.sql("""select item_code, count(name) as cnt from `tabStock Ledger Entry` - where ifnull(serial_no, '') != '' group by item_code""", as_dict=1): - sle_with_serial.setdefault(d.item_code, d.cnt) - - return sle_with_serial - -def get_items_with_batch(): - return frappe.db.sql_list("select item from tabBatch") - -def get_items_with_serial(): - return frappe.db.sql_list("select item_code from `tabSerial No`") diff --git a/erpnext/patches/v4_2/toggle_rounded_total.py b/erpnext/patches/v4_2/toggle_rounded_total.py deleted file mode 100644 index e571208eb65..00000000000 --- a/erpnext/patches/v4_2/toggle_rounded_total.py +++ /dev/null @@ -1,9 +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 - -def execute(): - global_defaults = frappe.get_doc("Global Defaults", "Global Defaults") - global_defaults.toggle_rounded_total() diff --git a/erpnext/patches/v4_2/update_landed_cost_voucher.py b/erpnext/patches/v4_2/update_landed_cost_voucher.py deleted file mode 100644 index ec0029671e4..00000000000 --- a/erpnext/patches/v4_2/update_landed_cost_voucher.py +++ /dev/null @@ -1,10 +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 - -def execute(): - frappe.reload_doc("stock", "doctype", "landed_cost_voucher") - frappe.db.sql("""update `tabLanded Cost Voucher` set distribute_charges_based_on = 'Amount' - where docstatus=1""") diff --git a/erpnext/patches/v4_2/update_project_milestones.py b/erpnext/patches/v4_2/update_project_milestones.py deleted file mode 100644 index e704116d05c..00000000000 --- a/erpnext/patches/v4_2/update_project_milestones.py +++ /dev/null @@ -1,9 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - for project in frappe.db.sql_list("select name from tabProject"): - frappe.reload_doc("projects", "doctype", "project") - p = frappe.get_doc("Project", project) - p.update_milestones_completed() - p.db_set("percent_milestones_completed", p.percent_milestones_completed) diff --git a/erpnext/patches/v4_2/update_sales_order_invoice_field_name.py b/erpnext/patches/v4_2/update_sales_order_invoice_field_name.py deleted file mode 100644 index 28dd5c0d4e7..00000000000 --- a/erpnext/patches/v4_2/update_sales_order_invoice_field_name.py +++ /dev/null @@ -1,7 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doc('accounts', 'doctype', 'sales_invoice') - frappe.db.sql("""update `tabSales Invoice` set from_date = invoice_period_from_date, - to_date = invoice_period_to_date, is_recurring = convert_into_recurring_invoice""") diff --git a/erpnext/patches/v4_2/update_stock_uom_for_dn_in_sle.py b/erpnext/patches/v4_2/update_stock_uom_for_dn_in_sle.py deleted file mode 100644 index 89bf7955340..00000000000 --- a/erpnext/patches/v4_2/update_stock_uom_for_dn_in_sle.py +++ /dev/null @@ -1,11 +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 - -def execute(): - frappe.db.sql("""update `tabStock Ledger Entry` sle, tabItem item - set sle.stock_uom = item.stock_uom - where sle.voucher_type="Delivery Note" and item.name = sle.item_code - and sle.stock_uom != item.stock_uom""") diff --git a/erpnext/patches/v4_4/__init__.py b/erpnext/patches/v4_4/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/erpnext/patches/v4_4/make_email_accounts.py b/erpnext/patches/v4_4/make_email_accounts.py deleted file mode 100644 index 57df1ae4911..00000000000 --- a/erpnext/patches/v4_4/make_email_accounts.py +++ /dev/null @@ -1,96 +0,0 @@ -from __future__ import unicode_literals -import frappe -from frappe.model import default_fields - -from six import iteritems - -def execute(): - frappe.reload_doc("email", "doctype", "email_account") - - # outgoing - outgoing = dict(frappe.db.sql("select field, value from tabSingles where doctype='Outgoing Email Settings'")) - if outgoing and outgoing['mail_server'] and outgoing['mail_login']: - account = frappe.new_doc("Email Account") - mapping = { - "login_id_is_different": 1, - "email_id": "auto_email_id", - "login_id": "mail_login", - "password": "mail_password", - "footer": "footer", - "smtp_server": "mail_server", - "smtp_port": "mail_port", - "use_tls": "use_ssl" - } - - for target_fieldname, source_fieldname in iteritems(mapping): - account.set(target_fieldname, outgoing.get(source_fieldname)) - - account.enable_outgoing = 1 - account.enable_incoming = 0 - - account.insert() - - # support - support = dict(frappe.db.sql("select field, value from tabSingles where doctype='Support Email Settings'")) - if support and support['mail_server'] and support['mail_login']: - account = frappe.new_doc("Email Account") - mapping = { - "enable_incoming": "sync_support_mails", - "email_id": "mail_login", - "password": "mail_password", - "email_server": "mail_server", - "use_ssl": "use_ssl", - "signature": "support_signature", - "enable_auto_reply": "send_autoreply", - "auto_reply_message": "support_autoreply" - } - - for target_fieldname, source_fieldname in iteritems(mapping): - account.set(target_fieldname, support.get(source_fieldname)) - - account.enable_outgoing = 0 - account.append_to = "Issue" - - insert_or_update(account) - - # sales, jobs - for doctype in ("Sales Email Settings", "Jobs Email Settings"): - source = dict(frappe.db.sql("select field, value from tabSingles where doctype=%s", doctype)) - if source and source.get('host') and source.get('username'): - account = frappe.new_doc("Email Account") - mapping = { - "enable_incoming": "extract_emails", - "email_id": "username", - "password": "password", - "email_server": "host", - "use_ssl": "use_ssl", - } - - for target_fieldname, source_fieldname in iteritems(mapping): - account.set(target_fieldname, source.get(source_fieldname)) - - account.enable_outgoing = 0 - account.append_to = "Lead" if doctype=="Sales Email Settings" else "Job Applicant" - - insert_or_update(account) - - for doctype in ("Outgoing Email Settings", "Support Email Settings", - "Sales Email Settings", "Jobs Email Settings"): - frappe.delete_doc("DocType", doctype) - -def insert_or_update(account): - try: - account.insert() - except frappe.NameError as e: - if e.args[0]=="Email Account": - existing_account = frappe.get_doc("Email Account", e.args[1]) - for key, value in account.as_dict().items(): - if not existing_account.get(key) and value \ - and key not in default_fields \ - and key != "__islocal": - existing_account.set(key, value) - - existing_account.save() - else: - raise - diff --git a/erpnext/patches/v5_0/__init__.py b/erpnext/patches/v5_0/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/erpnext/patches/v5_0/convert_stock_reconciliation.py b/erpnext/patches/v5_0/convert_stock_reconciliation.py deleted file mode 100644 index 75d1da752f2..00000000000 --- a/erpnext/patches/v5_0/convert_stock_reconciliation.py +++ /dev/null @@ -1,31 +0,0 @@ -from __future__ import unicode_literals -import frappe, json - -def execute(): - # stock reco now amendable - frappe.db.sql("""update tabDocPerm set `amend` = 1 where parent='Stock Reconciliation' and submit = 1""") - - frappe.reload_doc("stock", "doctype", "stock_reconciliation_item") - frappe.reload_doctype("Stock Reconciliation") - - if frappe.db.has_column("Stock Reconciliation", "reconciliation_json"): - for sr in frappe.db.get_all("Stock Reconciliation", ["name"], - {"reconciliation_json": ["!=", ""]}): - start = False - sr = frappe.get_doc("Stock Reconciliation", sr.name) - for row in json.loads(sr.reconciliation_json): - if start: - sr.append("items", { - "item_code": row[0], - "warehouse": row[1], - "qty": row[2] if len(row) > 2 else None, - "valuation_rate": row[3] if len(row) > 3 else None - }) - - elif row[0]=="Item Code": - start = True - - - for item in sr.items: - item.db_update() - diff --git a/erpnext/patches/v5_0/execute_on_doctype_update.py b/erpnext/patches/v5_0/execute_on_doctype_update.py deleted file mode 100644 index 70b1d8ded69..00000000000 --- a/erpnext/patches/v5_0/execute_on_doctype_update.py +++ /dev/null @@ -1,9 +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 - -def execute(): - for dt in ("Stock Ledger Entry", "Communication", "DefaultValue", "DocShare", "File", "ToDo"): - frappe.get_doc("DocType", dt).run_module_method("on_doctype_update") diff --git a/erpnext/patches/v5_0/fix_taxes_and_totals_in_party_currency.py b/erpnext/patches/v5_0/fix_taxes_and_totals_in_party_currency.py deleted file mode 100644 index 30dc0f8db4e..00000000000 --- a/erpnext/patches/v5_0/fix_taxes_and_totals_in_party_currency.py +++ /dev/null @@ -1,66 +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.model.meta import get_field_precision - -def execute(): - if not frappe.db.sql("""select name from `tabPatch Log` - where patch = 'erpnext.patches.v5_0.taxes_and_totals_in_party_currency'"""): - return - selling_doctypes = ["Quotation", "Sales Order", "Delivery Note", "Sales Invoice"] - buying_doctypes = ["Supplier Quotation", "Purchase Order", "Purchase Receipt", "Purchase Invoice"] - - for dt in selling_doctypes: - update_values(dt, "Sales Taxes and Charges") - - for dt in buying_doctypes: - update_values(dt, "Purchase Taxes and Charges") - -def update_values(dt, tax_table): - rate_field_precision = get_field_precision(frappe.get_meta(dt + " Item").get_field("rate")) - tax_amount_precision = get_field_precision(frappe.get_meta(tax_table).get_field("tax_amount")) - - # update net_total, discount_on - frappe.db.sql(""" - UPDATE - `tab{0}` - SET - total_taxes_and_charges = round(base_total_taxes_and_charges / conversion_rate, {1}) - WHERE - docstatus < 2 - and ifnull(base_total_taxes_and_charges, 0) != 0 - and ifnull(total_taxes_and_charges, 0) = 0 - """.format(dt, tax_amount_precision)) - - # update net_amount - frappe.db.sql(""" - UPDATE - `tab{0}` par, `tab{1}` item - SET - item.net_amount = round(item.base_net_amount / par.conversion_rate, {2}), - item.net_rate = round(item.base_net_rate / par.conversion_rate, {2}) - WHERE - par.name = item.parent - and par.docstatus < 2 - and ((ifnull(item.base_net_amount, 0) != 0 and ifnull(item.net_amount, 0) = 0) - or (ifnull(item.base_net_rate, 0) != 0 and ifnull(item.net_rate, 0) = 0)) - """.format(dt, dt + " Item", rate_field_precision)) - - # update tax in party currency - frappe.db.sql(""" - UPDATE - `tab{0}` par, `tab{1}` tax - SET - tax.tax_amount = round(tax.base_tax_amount / par.conversion_rate, {2}), - tax.total = round(tax.base_total / conversion_rate, {2}), - tax.tax_amount_after_discount_amount = round(tax.base_tax_amount_after_discount_amount / conversion_rate, {2}) - WHERE - par.name = tax.parent - and par.docstatus < 2 - and ((ifnull(tax.base_tax_amount, 0) != 0 and ifnull(tax.tax_amount, 0) = 0) - or (ifnull(tax.base_total, 0) != 0 and ifnull(tax.total, 0) = 0) - or (ifnull(tax.base_tax_amount_after_discount_amount, 0) != 0 and - ifnull(tax.tax_amount_after_discount_amount, 0) = 0)) - """.format(dt, tax_table, tax_amount_precision)) \ No newline at end of file diff --git a/erpnext/patches/v5_0/index_on_account_and_gl_entry.py b/erpnext/patches/v5_0/index_on_account_and_gl_entry.py deleted file mode 100644 index 2920e9293d7..00000000000 --- a/erpnext/patches/v5_0/index_on_account_and_gl_entry.py +++ /dev/null @@ -1,30 +0,0 @@ -from __future__ import unicode_literals - -import frappe - -def execute(): - index_map = { - "Account": ["parent_account", "lft", "rgt"], - "GL Entry": ["posting_date", "account", 'party', "voucher_no"], - "Sales Invoice": ["posting_date", "debit_to", "customer"], - "Purchase Invoice": ["posting_date", "credit_to", "supplier"] - } - - for dt, indexes in index_map.items(): - existing_indexes = [(d.Key_name, d.Column_name) for d in frappe.db.sql("""show index from `tab{0}` - where Column_name != 'name'""".format(dt), as_dict=1)] - - for old, column in existing_indexes: - if column in ("parent", "group_or_ledger", "is_group", "is_pl_account", "debit_or_credit", - "account_name", "company", "project", "voucher_date", "due_date", "bill_no", - "bill_date", "is_opening", "fiscal_year", "outstanding_amount"): - frappe.db.sql("alter table `tab{0}` drop index {1}".format(dt, old)) - - existing_indexes = [(d.Key_name, d.Column_name) for d in frappe.db.sql("""show index from `tab{0}` - where Column_name != 'name'""".format(dt), as_dict=1)] - - existing_indexed_columns = list(set([x[1] for x in existing_indexes])) - - for new in indexes: - if new not in existing_indexed_columns: - frappe.db.sql("alter table `tab{0}` add index ({1})".format(dt, new)) \ No newline at end of file diff --git a/erpnext/patches/v5_0/is_group.py b/erpnext/patches/v5_0/is_group.py deleted file mode 100644 index 4e3f760bed7..00000000000 --- a/erpnext/patches/v5_0/is_group.py +++ /dev/null @@ -1,9 +0,0 @@ -from __future__ import unicode_literals - -import frappe - -def execute(): - frappe.reload_doctype("Account") - frappe.reload_doctype("Cost Center") - frappe.db.sql("update tabAccount set is_group = if(group_or_ledger='Group', 1, 0)") - frappe.db.sql("update `tabCost Center` set is_group = if(group_or_ledger='Group', 1, 0)") diff --git a/erpnext/patches/v5_0/item_patches.py b/erpnext/patches/v5_0/item_patches.py deleted file mode 100644 index e223e09f5b7..00000000000 --- a/erpnext/patches/v5_0/item_patches.py +++ /dev/null @@ -1,6 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.db.sql("update `tabItem` set end_of_life='2099-12-31' where ifnull(end_of_life, '0000-00-00')='0000-00-00'") - frappe.db.sql("update `tabItem` set website_image = image where ifnull(website_image, '') = 'attach_files:'") diff --git a/erpnext/patches/v5_0/link_warehouse_with_account.py b/erpnext/patches/v5_0/link_warehouse_with_account.py deleted file mode 100644 index 338fd7ad7f6..00000000000 --- a/erpnext/patches/v5_0/link_warehouse_with_account.py +++ /dev/null @@ -1,10 +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 - -def execute(): - if "master_name" in frappe.db.get_table_columns("Account"): - frappe.db.sql("""update tabAccount set warehouse=master_name - where ifnull(account_type, '') = 'Warehouse' and ifnull(master_name, '') != ''""") \ No newline at end of file diff --git a/erpnext/patches/v5_0/new_crm_module.py b/erpnext/patches/v5_0/new_crm_module.py deleted file mode 100644 index f5dda1f2738..00000000000 --- a/erpnext/patches/v5_0/new_crm_module.py +++ /dev/null @@ -1,24 +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 json -import frappe - -def execute(): - frappe.reload_doc('crm', 'doctype', 'lead') - frappe.reload_doc('crm', 'doctype', 'opportunity') - - add_crm_to_user_desktop_items() - -def add_crm_to_user_desktop_items(): - key = "_user_desktop_items" - for user in frappe.get_all("User", filters={"enabled": 1, "user_type": "System User"}): - user = user.name - user_desktop_items = frappe.db.get_defaults(key, parent=user) - if user_desktop_items: - user_desktop_items = json.loads(user_desktop_items) - if "CRM" not in user_desktop_items: - user_desktop_items.append("CRM") - frappe.db.set_default(key, json.dumps(user_desktop_items), parent=user) - diff --git a/erpnext/patches/v5_0/newsletter.py b/erpnext/patches/v5_0/newsletter.py deleted file mode 100644 index 63e33124139..00000000000 --- a/erpnext/patches/v5_0/newsletter.py +++ /dev/null @@ -1,38 +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 -import frappe.permissions - -def execute(): - frappe.reload_doc("core", "doctype", "block_module") - frappe.reload_doctype("User") - frappe.reload_doctype("Lead") - frappe.reload_doctype("Contact") - - frappe.reload_doc('email', 'doctype', 'email_group') - frappe.reload_doc('email', 'doctype', 'email_group_member') - frappe.reload_doc('email', 'doctype', 'newsletter') - - frappe.permissions.reset_perms("Newsletter") - - if not frappe.db.exists("Role", "Newsletter Manager"): - frappe.get_doc({"doctype": "Role", "role": "Newsletter Manager"}).insert() - - for userrole in frappe.get_all("Has Role", "parent", {"role": "Sales Manager", "parenttype": "User"}): - if frappe.db.exists("User", userrole.parent): - user = frappe.get_doc("User", userrole.parent) - user.append("roles", { - "doctype": "Has Role", - "role": "Newsletter Manager" - }) - user.flags.ignore_mandatory = True - user.save() - - # create default lists - general = frappe.new_doc("Email Group") - general.title = "General" - general.insert() - general.import_from("Lead") - general.import_from("Contact") diff --git a/erpnext/patches/v5_0/opportunity_not_submittable.py b/erpnext/patches/v5_0/opportunity_not_submittable.py deleted file mode 100644 index e29d66f2845..00000000000 --- a/erpnext/patches/v5_0/opportunity_not_submittable.py +++ /dev/null @@ -1,10 +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 - -def execute(): - frappe.reload_doctype("Opportunity") - frappe.db.sql("update tabDocPerm set submit=0, cancel=0, amend=0 where parent='Opportunity'") - frappe.db.sql("update tabOpportunity set docstatus=0 where docstatus=1") diff --git a/erpnext/patches/v5_0/party_model_patch_fix.py b/erpnext/patches/v5_0/party_model_patch_fix.py deleted file mode 100644 index d9b67097922..00000000000 --- a/erpnext/patches/v5_0/party_model_patch_fix.py +++ /dev/null @@ -1,18 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - for company in frappe.get_all("Company", - ["name", "default_receivable_account", "default_payable_account"]): - - if company.default_receivable_account: - frappe.db.sql("""update `tabSales Invoice` invoice set `debit_to`=%(account)s - where company=%(company)s - and not exists (select name from `tabAccount` account where account.name=invoice.debit_to)""", - {"company": company.name, "account": company.default_receivable_account}) - - if company.default_payable_account: - frappe.db.sql("""update `tabPurchase Invoice` invoice set `credit_to`=%(account)s - where company=%(company)s - and not exists (select name from `tabAccount` account where account.name=invoice.credit_to)""", - {"company": company.name, "account": company.default_payable_account}) diff --git a/erpnext/patches/v5_0/portal_fixes.py b/erpnext/patches/v5_0/portal_fixes.py deleted file mode 100644 index 1fefd991678..00000000000 --- a/erpnext/patches/v5_0/portal_fixes.py +++ /dev/null @@ -1,7 +0,0 @@ -from __future__ import unicode_literals -import frappe -import erpnext.setup.install - -def execute(): - frappe.reload_doc("website", "doctype", "web_form_field", force=True, reset_permissions=True) - #erpnext.setup.install.add_web_forms() diff --git a/erpnext/patches/v5_0/project_costing.py b/erpnext/patches/v5_0/project_costing.py deleted file mode 100644 index e2d65d05940..00000000000 --- a/erpnext/patches/v5_0/project_costing.py +++ /dev/null @@ -1,8 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doctype("Project") - frappe.db.sql("update `tabProject` set expected_start_date = project_start_date, \ - expected_end_date = completion_date, actual_end_date = act_completion_date, \ - estimated_costing = project_value, gross_margin = gross_margin_value") \ No newline at end of file diff --git a/erpnext/patches/v5_0/recalculate_total_amount_in_jv.py b/erpnext/patches/v5_0/recalculate_total_amount_in_jv.py deleted file mode 100644 index d5af43c541e..00000000000 --- a/erpnext/patches/v5_0/recalculate_total_amount_in_jv.py +++ /dev/null @@ -1,26 +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.utils import money_in_words - -def execute(): - company_currency = dict(frappe.db.sql("select name, default_currency from `tabCompany`")) - bank_or_cash_accounts = frappe.db.sql_list("""select name from `tabAccount` - where account_type in ('Bank', 'Cash') and docstatus < 2""") - - for je in frappe.db.sql_list("""select name from `tabJournal Entry` where docstatus < 2"""): - total_amount = 0 - total_amount_in_words = "" - - je_doc = frappe.get_doc('Journal Entry', je) - for d in je_doc.get("accounts"): - if (d.party_type and d.party) or d.account in bank_or_cash_accounts: - total_amount = d.debit or d.credit - if total_amount: - total_amount_in_words = money_in_words(total_amount, company_currency.get(je_doc.company)) - - if total_amount: - frappe.db.sql("""update `tabJournal Entry` set total_amount=%s, total_amount_in_words=%s - where name = %s""", (total_amount, total_amount_in_words, je)) diff --git a/erpnext/patches/v5_0/reclculate_planned_operating_cost_in_production_order.py b/erpnext/patches/v5_0/reclculate_planned_operating_cost_in_production_order.py deleted file mode 100644 index 6d392831b40..00000000000 --- a/erpnext/patches/v5_0/reclculate_planned_operating_cost_in_production_order.py +++ /dev/null @@ -1,13 +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 - -def execute(): - for wo in frappe.db.sql("""select name from `tabWork Order` where docstatus < 2""", as_dict=1): - work_order = frappe.get_doc("Work Order", wo.name) - if work_order.operations: - work_order.flags.ignore_validate_update_after_submit = True - work_order.calculate_time() - work_order.save() \ No newline at end of file diff --git a/erpnext/patches/v5_0/remove_birthday_events.py b/erpnext/patches/v5_0/remove_birthday_events.py deleted file mode 100644 index 3ead8669b86..00000000000 --- a/erpnext/patches/v5_0/remove_birthday_events.py +++ /dev/null @@ -1,7 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - for e in frappe.db.sql_list("""select name from tabEvent where - repeat_on='Every Year' and ref_type='Employee'"""): - frappe.delete_doc("Event", e, force=True) diff --git a/erpnext/patches/v5_0/rename_customer_issue.py b/erpnext/patches/v5_0/rename_customer_issue.py deleted file mode 100644 index 1bd69ceec19..00000000000 --- a/erpnext/patches/v5_0/rename_customer_issue.py +++ /dev/null @@ -1,6 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - if frappe.db.table_exists("Customer Issue"): - frappe.rename_doc("DocType", "Customer Issue", "Warranty Claim") diff --git a/erpnext/patches/v5_0/rename_pos_setting.py b/erpnext/patches/v5_0/rename_pos_setting.py deleted file mode 100644 index bf10333564e..00000000000 --- a/erpnext/patches/v5_0/rename_pos_setting.py +++ /dev/null @@ -1,6 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - if frappe.db.table_exists("POS Setting"): - frappe.rename_doc("DocType", "POS Setting", "POS Profile") diff --git a/erpnext/patches/v5_0/rename_table_fieldnames.py b/erpnext/patches/v5_0/rename_table_fieldnames.py deleted file mode 100644 index aefb0a20372..00000000000 --- a/erpnext/patches/v5_0/rename_table_fieldnames.py +++ /dev/null @@ -1,243 +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.model.utils.rename_field import rename_field -from frappe.modules import scrub, get_doctype_module - -rename_map = { - "Opportunity": [ - ["enquiry_details", "items"] - ], - "Quotation": [ - ["quotation_details", "items"], - ["other_charges", "taxes"] - ], - "Sales Order": [ - ["sales_order_details", "items"], - ["other_charges", "taxes"], - ["packing_details", "packed_items"] - ], - "Delivery Note": [ - ["delivery_note_details", "items"], - ["other_charges", "taxes"], - ["packing_details", "packed_items"] - ], - "Sales Invoice": [ - ["entries", "items"], - ["other_charges", "taxes"], - ["packing_details", "packed_items"], - ["advance_adjustment_details", "advances"] - ], - "Material Request": [ - ["indent_details", "items"] - ], - "Supplier Quotation": [ - ["quotation_items", "items"], - ["other_charges", "taxes"] - ], - "Purchase Order": [ - ["po_details", "items"], - ["other_charges", "taxes"], - ["po_raw_material_details", "supplied_items"] - ], - "Purchase Receipt": [ - ["purchase_receipt_details", "items"], - ["other_charges", "taxes"], - ["pr_raw_material_details", "supplied_items"] - ], - "Purchase Invoice": [ - ["entries", "items"], - ["other_charges", "taxes"], - ["advance_allocation_details", "advances"] - ], - "Work Order": [ - ["production_order_operations", "operations"] - ], - "BOM": [ - ["bom_operations", "operations"], - ["bom_materials", "items"], - ["flat_bom_details", "exploded_items"] - ], - "Payment Reconciliation": [ - ["payment_reconciliation_payments", "payments"], - ["payment_reconciliation_invoices", "invoices"] - ], - "Sales Taxes and Charges Template": [ - ["other_charges", "taxes"], - ["valid_for_territories", "territories"] - ], - "Purchase Taxes and Charges Template": [ - ["other_charges", "taxes"] - ], - "Shipping Rule": [ - ["shipping_rule_conditions", "conditions"], - ["valid_for_territories", "territories"] - ], - "Price List": [ - ["valid_for_territories", "territories"] - ], - "Appraisal": [ - ["appraisal_details", "goals"] - ], - "Appraisal Template": [ - ["kra_sheet", "goals"] - ], - "Bank Reconciliation": [ - ["entries", "journal_entries"] - ], - "C-Form": [ - ["invoice_details", "invoices"] - ], - "Employee": [ - ["employee_leave_approvers", "leave_approvers"], - ["educational_qualification_details", "education"], - ["previous_experience_details", "external_work_history"], - ["experience_in_company_details", "internal_work_history"] - ], - "Expense Claim": [ - ["expense_voucher_details", "expenses"] - ], - "Fiscal Year": [ - ["fiscal_year_companies", "companies"] - ], - "Holiday List": [ - ["holiday_list_details", "holidays"] - ], - "Installation Note": [ - ["installed_item_details", "items"] - ], - "Item": [ - ["item_reorder", "reorder_levels"], - ["uom_conversion_details", "uoms"], - ["item_supplier_details", "supplier_items"], - ["item_customer_details", "customer_items"], - ["item_tax", "taxes"], - ["item_specification_details", "quality_parameters"], - ["item_website_specifications", "website_specifications"] - ], - "Item Group": [ - ["item_website_specifications", "website_specifications"] - ], - "Landed Cost Voucher": [ - ["landed_cost_purchase_receipts", "purchase_receipts"], - ["landed_cost_items", "items"], - ["landed_cost_taxes_and_charges", "taxes"] - ], - "Maintenance Schedule": [ - ["item_maintenance_detail", "items"], - ["maintenance_schedule_detail", "schedules"] - ], - "Maintenance Visit": [ - ["maintenance_visit_details", "purposes"] - ], - "Packing Slip": [ - ["item_details", "items"] - ], - "Customer": [ - ["party_accounts", "accounts"] - ], - "Customer Group": [ - ["party_accounts", "accounts"] - ], - "Supplier": [ - ["party_accounts", "accounts"] - ], - "Supplier Type": [ - ["party_accounts", "accounts"] - ], - "Payment Tool": [ - ["payment_tool_details", "vouchers"] - ], - "Production Planning Tool": [ - ["pp_so_details", "sales_orders"], - ["pp_details", "items"] - ], - "Quality Inspection": [ - ["qa_specification_details", "readings"] - ], - "Salary Slip": [ - ["earning_details", "earnings"], - ["deduction_details", "deductions"] - ], - "Salary Structure": [ - ["earning_details", "earnings"], - ["deduction_details", "deductions"] - ], - "Product Bundle": [ - ["sales_bom_items", "items"] - ], - "SMS Settings": [ - ["static_parameter_details", "parameters"] - ], - "Stock Entry": [ - ["mtn_details", "items"] - ], - "Sales Partner": [ - ["partner_target_details", "targets"] - ], - "Sales Person": [ - ["target_details", "targets"] - ], - "Territory": [ - ["target_details", "targets"] - ], - "Time Sheet": [ - ["time_sheet_details", "time_logs"] - ], - "Workstation": [ - ["workstation_operation_hours", "working_hours"] - ], - "Payment Reconciliation Payment": [ - ["journal_voucher", "journal_entry"], - ], - "Purchase Invoice Advance": [ - ["journal_voucher", "journal_entry"], - ], - "Sales Invoice Advance": [ - ["journal_voucher", "journal_entry"], - ], - "Journal Entry": [ - ["entries", "accounts"] - ], - "Monthly Distribution": [ - ["budget_distribution_details", "percentages"] - ] -} - -def execute(): - # rename doctypes - tables = frappe.db.sql_list("show tables") - for old_dt, new_dt in [["Journal Voucher Detail", "Journal Entry Account"], - ["Journal Voucher", "Journal Entry"], - ["Budget Distribution Detail", "Monthly Distribution Percentage"], - ["Budget Distribution", "Monthly Distribution"]]: - if "tab"+new_dt not in tables: - frappe.rename_doc("DocType", old_dt, new_dt, force=True) - - # reload new child doctypes - frappe.reload_doc("manufacturing", "doctype", "work_order_operation") - frappe.reload_doc("manufacturing", "doctype", "workstation_working_hour") - frappe.reload_doc("stock", "doctype", "item_variant") - frappe.reload_doc("Payroll", "doctype", "salary_detail") - frappe.reload_doc("accounts", "doctype", "party_account") - frappe.reload_doc("accounts", "doctype", "fiscal_year_company") - - #rename table fieldnames - for dn in rename_map: - if not frappe.db.exists("DocType", dn): - continue - frappe.reload_doc(get_doctype_module(dn), "doctype", scrub(dn)) - - for dt, field_list in rename_map.items(): - if not frappe.db.exists("DocType", dt): - continue - for field in field_list: - rename_field(dt, field[0], field[1]) - - # update voucher type - for old, new in [["Bank Voucher", "Bank Entry"], ["Cash Voucher", "Cash Entry"], - ["Credit Card Voucher", "Credit Card Entry"], ["Contra Voucher", "Contra Entry"], - ["Write Off Voucher", "Write Off Entry"], ["Excise Voucher", "Excise Entry"]]: - frappe.db.sql("update `tabJournal Entry` set voucher_type=%s where voucher_type=%s", (new, old)) diff --git a/erpnext/patches/v5_0/rename_taxes_and_charges_master.py b/erpnext/patches/v5_0/rename_taxes_and_charges_master.py deleted file mode 100644 index e26f48cda18..00000000000 --- a/erpnext/patches/v5_0/rename_taxes_and_charges_master.py +++ /dev/null @@ -1,14 +0,0 @@ -from __future__ import unicode_literals -import frappe - - -def execute(): - if frappe.db.table_exists("Sales Taxes and Charges Master"): - frappe.rename_doc("DocType", "Sales Taxes and Charges Master", - "Sales Taxes and Charges Template") - frappe.delete_doc("DocType", "Sales Taxes and Charges Master") - - if frappe.db.table_exists("Purchase Taxes and Charges Master"): - frappe.rename_doc("DocType", "Purchase Taxes and Charges Master", - "Purchase Taxes and Charges Template") - frappe.delete_doc("DocType", "Purchase Taxes and Charges Master") diff --git a/erpnext/patches/v5_0/rename_total_fields.py b/erpnext/patches/v5_0/rename_total_fields.py deleted file mode 100644 index 6657dd843e8..00000000000 --- a/erpnext/patches/v5_0/rename_total_fields.py +++ /dev/null @@ -1,55 +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.model.utils.rename_field import rename_field -from frappe.modules import scrub, get_doctype_module - -selling_doctypes = ("Quotation", "Sales Order", "Delivery Note", "Sales Invoice") - -buying_doctypes = ("Supplier Quotation", "Purchase Order", "Purchase Receipt", "Purchase Invoice") - -selling_renamed_fields = ( - ("net_total", "base_net_total"), - ("net_total_export", "net_total"), - ("other_charges_total", "base_total_taxes_and_charges"), - ("other_charges_total_export", "total_taxes_and_charges"), - ("grand_total", "base_grand_total"), - ("grand_total_export", "grand_total"), - ("rounded_total", "base_rounded_total"), - ("rounded_total_export", "rounded_total"), - ("in_words", "base_in_words"), - ("in_words_export", "in_words") -) - -buying_renamed_fields = ( - ("net_total", "base_net_total"), - ("net_total_import", "net_total"), - ("grand_total", "base_grand_total"), - ("grand_total_import", "grand_total"), - ("rounded_total", "base_rounded_total"), - ("in_words", "base_in_words"), - ("in_words_import", "in_words"), - ("other_charges_added", "base_taxes_and_charges_added"), - ("other_charges_added_import", "taxes_and_charges_added"), - ("other_charges_deducted", "base_taxes_and_charges_deducted"), - ("other_charges_deducted_import", "taxes_and_charges_deducted"), - ("total_tax", "base_total_taxes_and_charges") -) - -def execute(): - for doctypes, fields in [[selling_doctypes, selling_renamed_fields], [buying_doctypes, buying_renamed_fields]]: - for dt in doctypes: - frappe.reload_doc(get_doctype_module(dt), "doctype", scrub(dt)) - table_columns = frappe.db.get_table_columns(dt) - base_net_total = frappe.db.sql("select sum(ifnull({0}, 0)) from `tab{1}`".format(fields[0][1], dt))[0][0] - if not base_net_total: - for f in fields: - if f[0] in table_columns: - rename_field(dt, f[0], f[1]) - - # Added new field "total_taxes_and_charges" in buying cycle, updating value - if dt in ("Supplier Quotation", "Purchase Order", "Purchase Receipt", "Purchase Invoice"): - frappe.db.sql("""update `tab{0}` set total_taxes_and_charges = - round(base_total_taxes_and_charges/conversion_rate, 2)""".format(dt)) diff --git a/erpnext/patches/v5_0/replace_renamed_fields_in_custom_scripts_and_print_formats.py b/erpnext/patches/v5_0/replace_renamed_fields_in_custom_scripts_and_print_formats.py deleted file mode 100644 index c564f8b02ab..00000000000 --- a/erpnext/patches/v5_0/replace_renamed_fields_in_custom_scripts_and_print_formats.py +++ /dev/null @@ -1,65 +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 -import re - -def execute(): - # NOTE: sequence is important - renamed_fields = get_all_renamed_fields() - - for dt, script_field, ref_dt_field in (("Client Script", "script", "dt"), ("Print Format", "html", "doc_type")): - - cond1 = " or ".join("""{0} like "%%{1}%%" """.format(script_field, d[0].replace("_", "\\_")) for d in renamed_fields) - cond2 = " and standard = 'No'" if dt == "Print Format" else "" - - for name, script, ref_dt in frappe.db.sql("select name, {0} as script, {1} as ref_dt from `tab{2}` where ({3}) {4}".format(script_field, ref_dt_field, dt, cond1, cond2)): - update_script(dt, name, ref_dt, script_field, script, renamed_fields) - -def get_all_renamed_fields(): - from erpnext.patches.v5_0.rename_table_fieldnames import rename_map - - renamed_fields = ( - ("base_amount", "base_net_amount"), - ("net_total", "base_net_total"), - ("net_total_export", "total"), - ("net_total_import", "total"), - ("other_charges_total", "base_total_taxes_and_charges"), - ("other_charges_total_export", "total_taxes_and_charges"), - ("other_charges_added", "base_taxes_and_charges_added"), - ("other_charges_added_import", "taxes_and_charges_added"), - ("other_charges_deducted", "base_taxes_and_charges_deducted"), - ("other_charges_deducted_import", "taxes_and_charges_deducted"), - ("total_tax", "base_total_taxes_and_charges"), - ("grand_total", "base_grand_total"), - ("grand_total_export", "grand_total"), - ("grand_total_import", "grand_total"), - ("rounded_total", "base_rounded_total"), - ("rounded_total_export", "rounded_total"), - ("rounded_total_import", "rounded_total"), - ("in_words", "base_in_words"), - ("in_words_export", "in_words"), - ("in_words_import", "in_words"), - ("tax_amount", "base_tax_amount"), - ("tax_amount_after_discount_amount", "base_tax_amount_after_discount_amount"), - ) - - for fields in rename_map.values(): - renamed_fields += tuple(fields) - - return renamed_fields - -def update_script(dt, name, ref_dt, script_field, script, renamed_fields): - for from_field, to_field in renamed_fields: - if from_field != "entries": - script = re.sub(r"\b{}\b".format(from_field), to_field, script) - - if ref_dt == "Journal Entry": - script = re.sub(r"\bentries\b", "accounts", script) - elif ref_dt == "Bank Reconciliation": - script = re.sub(r"\bentries\b", "journal_entries", script) - elif ref_dt in ("Sales Invoice", "Purchase Invoice"): - script = re.sub(r"\bentries\b", "items", script) - - frappe.db.set_value(dt, name, script_field, script) \ No newline at end of file diff --git a/erpnext/patches/v5_0/repost_gle_for_jv_with_multiple_party.py b/erpnext/patches/v5_0/repost_gle_for_jv_with_multiple_party.py deleted file mode 100644 index 76efdcc7c6b..00000000000 --- a/erpnext/patches/v5_0/repost_gle_for_jv_with_multiple_party.py +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import print_function, unicode_literals -import frappe - -def execute(): - je_list = frappe.db.sql_list(""" - select par.name from `tabJournal Entry` par - where par.docstatus=1 and par.creation > '2015-03-01' - and (select count(distinct child.party) from `tabJournal Entry Account` child - where par.name=child.parent and ifnull(child.party, '') != '') > 1 - """) - - for d in je_list: - # delete existing gle - frappe.db.sql("delete from `tabGL Entry` where voucher_type='Journal Entry' and voucher_no=%s", d) - - # repost gl entries - je = frappe.get_doc("Journal Entry", d) - je.make_gl_entries() - - if je_list: - print(je_list) - - \ No newline at end of file diff --git a/erpnext/patches/v5_0/repost_requested_qty.py b/erpnext/patches/v5_0/repost_requested_qty.py deleted file mode 100644 index 6af71f3fc49..00000000000 --- a/erpnext/patches/v5_0/repost_requested_qty.py +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - from erpnext.stock.stock_balance import update_bin_qty, get_indented_qty - - count=0 - for item_code, warehouse in frappe.db.sql("""select distinct item_code, warehouse - from `tabMaterial Request Item` where docstatus = 1"""): - try: - count += 1 - update_bin_qty(item_code, warehouse, { - "indented_qty": get_indented_qty(item_code, warehouse), - }) - if count % 200 == 0: - frappe.db.commit() - except: - frappe.db.rollback() diff --git a/erpnext/patches/v5_0/reset_values_in_tools.py b/erpnext/patches/v5_0/reset_values_in_tools.py deleted file mode 100644 index fd970ba1b04..00000000000 --- a/erpnext/patches/v5_0/reset_values_in_tools.py +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - for dt in ["Payment Tool", "Bank Reconciliation", "Payment Reconciliation", "Leave Control Panel", - "Salary Manager", "Upload Attenadance", "Production Planning Tool", "BOM Update Tool", "Customize Form", - "Employee Attendance Tool", "Rename Tool", "BOM Update Tool", "Process Payroll", "Naming Series"]: - frappe.db.sql("delete from `tabSingles` where doctype=%s", dt) - \ No newline at end of file diff --git a/erpnext/patches/v5_0/set_appraisal_remarks.py b/erpnext/patches/v5_0/set_appraisal_remarks.py deleted file mode 100644 index 8652c32cf0e..00000000000 --- a/erpnext/patches/v5_0/set_appraisal_remarks.py +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doctype("Appraisal") - frappe.db.sql("update `tabAppraisal` set remarks = comments") \ No newline at end of file diff --git a/erpnext/patches/v5_0/set_default_company_in_bom.py b/erpnext/patches/v5_0/set_default_company_in_bom.py deleted file mode 100644 index a5cd7611199..00000000000 --- a/erpnext/patches/v5_0/set_default_company_in_bom.py +++ /dev/null @@ -1,10 +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 - -def execute(): - frappe.reload_doc("manufacturing", "doctype", "bom") - company = frappe.db.get_value("Global Defaults", None, "default_company") - frappe.db.sql("""update `tabBOM` set company = %s""",company) diff --git a/erpnext/patches/v5_0/set_footer_address.py b/erpnext/patches/v5_0/set_footer_address.py deleted file mode 100644 index 8120d834e1f..00000000000 --- a/erpnext/patches/v5_0/set_footer_address.py +++ /dev/null @@ -1,9 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doctype("System Settings") - ss = frappe.get_doc("System Settings", "System Settings") - ss.email_footer_address = frappe.db.get_default("company") - ss.flags.ignore_mandatory = True - ss.save() diff --git a/erpnext/patches/v5_0/stock_entry_update_value.py b/erpnext/patches/v5_0/stock_entry_update_value.py deleted file mode 100644 index ba1af310f55..00000000000 --- a/erpnext/patches/v5_0/stock_entry_update_value.py +++ /dev/null @@ -1,8 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - for d in frappe.db.get_all("Stock Entry"): - se = frappe.get_doc("Stock Entry", d.name) - se.set_total_incoming_outgoing_value() - se.db_update() diff --git a/erpnext/patches/v5_0/taxes_and_totals_in_party_currency.py b/erpnext/patches/v5_0/taxes_and_totals_in_party_currency.py deleted file mode 100644 index 76d10820b58..00000000000 --- a/erpnext/patches/v5_0/taxes_and_totals_in_party_currency.py +++ /dev/null @@ -1,80 +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.model.meta import get_field_precision -from frappe.custom.doctype.property_setter.property_setter import make_property_setter - -def execute(): - selling_doctypes = ["Quotation", "Sales Order", "Delivery Note", "Sales Invoice"] - buying_doctypes = ["Supplier Quotation", "Purchase Order", "Purchase Receipt", "Purchase Invoice"] - - for dt in selling_doctypes: - update_values(dt, "Sales Taxes and Charges") - - for dt in buying_doctypes: - update_values(dt, "Purchase Taxes and Charges") - -def update_values(dt, tax_table): - frappe.reload_doctype(dt) - frappe.reload_doctype(dt + " Item") - frappe.reload_doctype(tax_table) - - net_total_precision = get_field_precision(frappe.get_meta(dt).get_field("net_total")) - for field in ("total", "base_total", "base_net_total"): - make_property_setter(dt, field, "precision", net_total_precision, "Select") - - rate_field_precision = get_field_precision(frappe.get_meta(dt + " Item").get_field("rate")) - for field in ("net_rate", "base_net_rate", "net_amount", "base_net_amount", "base_rate", "base_amount"): - make_property_setter(dt + " Item", field, "precision", rate_field_precision, "Select") - - tax_amount_precision = get_field_precision(frappe.get_meta(tax_table).get_field("tax_amount")) - for field in ("base_tax_amount", "total", "base_total", "tax_amount_after_discount_amount", - "base_tax_amount_after_discount_amount"): - make_property_setter(tax_table, field, "precision", tax_amount_precision, "Select") - - # update net_total, discount_on - frappe.db.sql(""" - UPDATE - `tab{0}` - SET - total = round(net_total, {1}), - base_total = round(net_total*conversion_rate, {1}), - net_total = round(base_net_total / conversion_rate, {1}), - apply_discount_on = "Grand Total" - WHERE - docstatus < 2 - """.format(dt, net_total_precision)) - - # update net_amount - frappe.db.sql(""" - UPDATE - `tab{0}` par, `tab{1}` item - SET - item.base_net_amount = round(item.base_amount, {2}), - item.base_net_rate = round(item.base_rate, {2}), - item.net_amount = round(item.base_amount / par.conversion_rate, {2}), - item.net_rate = round(item.base_rate / par.conversion_rate, {2}), - item.base_amount = round(item.amount * par.conversion_rate, {2}), - item.base_rate = round(item.rate * par.conversion_rate, {2}) - WHERE - par.name = item.parent - and par.docstatus < 2 - """.format(dt, dt + " Item", rate_field_precision)) - - # update tax in party currency - frappe.db.sql(""" - UPDATE - `tab{0}` par, `tab{1}` tax - SET - tax.base_tax_amount = round(tax.tax_amount, {2}), - tax.tax_amount = round(tax.tax_amount / par.conversion_rate, {2}), - tax.base_total = round(tax.total, {2}), - tax.total = round(tax.total / conversion_rate, {2}), - tax.base_tax_amount_after_discount_amount = round(tax.tax_amount_after_discount_amount, {2}), - tax.tax_amount_after_discount_amount = round(tax.tax_amount_after_discount_amount / conversion_rate, {2}) - WHERE - par.name = tax.parent - and par.docstatus < 2 - """.format(dt, tax_table, tax_amount_precision)) diff --git a/erpnext/patches/v5_0/update_account_types.py b/erpnext/patches/v5_0/update_account_types.py deleted file mode 100644 index 424743efaa7..00000000000 --- a/erpnext/patches/v5_0/update_account_types.py +++ /dev/null @@ -1,20 +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 - -def execute(): - for company in frappe.db.get_all("Company"): - company = frappe.get_doc("Company", company.name) - - match_types = ("Stock Received But Not Billed", "Stock Adjustment", "Expenses Included In Valuation", - "Cost of Goods Sold") - - for account_type in match_types: - account_name = "{0} - {1}".format(account_type, company.abbr) - current_account_type = frappe.db.get_value("Account", account_name, "account_type") - if current_account_type != account_type: - frappe.db.set_value("Account", account_name, "account_type", account_type) - - company.set_default_accounts() diff --git a/erpnext/patches/v5_0/update_advance_paid.py b/erpnext/patches/v5_0/update_advance_paid.py deleted file mode 100644 index 74e71e84c82..00000000000 --- a/erpnext/patches/v5_0/update_advance_paid.py +++ /dev/null @@ -1,13 +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 - -def execute(): - for dt in ("Sales Order", "Purchase Order"): - orders_with_advance = frappe.db.sql("""select name from `tab{0}` - where docstatus < 2 and ifnull(advance_paid, 0) != 0""".format(dt), as_dict=1) - - for order in orders_with_advance: - frappe.get_doc(dt, order.name).set_total_advance_paid() \ No newline at end of file diff --git a/erpnext/patches/v5_0/update_companywise_payment_account.py b/erpnext/patches/v5_0/update_companywise_payment_account.py deleted file mode 100644 index fb4b919c859..00000000000 --- a/erpnext/patches/v5_0/update_companywise_payment_account.py +++ /dev/null @@ -1,21 +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 - -def execute(): - frappe.reload_doc('accounts', 'doctype', 'mode_of_payment') - frappe.reload_doc('accounts', 'doctype', 'mode_of_payment_account') - - mode_of_payment_list = frappe.db.sql("""select name, default_account - from `tabMode of Payment`""", as_dict=1) - - for d in mode_of_payment_list: - if d.get("default_account"): - parent_doc = frappe.get_doc("Mode of Payment", d.get("name")) - - parent_doc.set("accounts", - [{"company": frappe.db.get_value("Account", d.get("default_account"), "company"), - "default_account": d.get("default_account")}]) - parent_doc.save() diff --git a/erpnext/patches/v5_0/update_dn_against_doc_fields.py b/erpnext/patches/v5_0/update_dn_against_doc_fields.py deleted file mode 100644 index 56f4f484b13..00000000000 --- a/erpnext/patches/v5_0/update_dn_against_doc_fields.py +++ /dev/null @@ -1,14 +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 - -def execute(): - frappe.reload_doc('stock', 'doctype', 'delivery_note_item') - - frappe.db.sql("""update `tabDelivery Note Item` set so_detail = prevdoc_detail_docname - where ifnull(against_sales_order, '') != ''""") - - frappe.db.sql("""update `tabDelivery Note Item` set si_detail = prevdoc_detail_docname - where ifnull(against_sales_invoice, '') != ''""") diff --git a/erpnext/patches/v5_0/update_from_bom.py b/erpnext/patches/v5_0/update_from_bom.py deleted file mode 100644 index 4b3e62d7a55..00000000000 --- a/erpnext/patches/v5_0/update_from_bom.py +++ /dev/null @@ -1,9 +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 - -def execute(): - frappe.reload_doctype("Stock Entry") - frappe.db.sql("update `tabStock Entry` set from_bom = if(ifnull(bom_no, '')='', 0, 1)") diff --git a/erpnext/patches/v5_0/update_frozen_accounts_permission_role.py b/erpnext/patches/v5_0/update_frozen_accounts_permission_role.py deleted file mode 100644 index b52785ae605..00000000000 --- a/erpnext/patches/v5_0/update_frozen_accounts_permission_role.py +++ /dev/null @@ -1,13 +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 - -def execute(): - account_settings = frappe.get_doc("Accounts Settings") - - if not account_settings.frozen_accounts_modifier and account_settings.bde_auth_role: - frappe.db.set_value("Accounts Settings", None, - "frozen_accounts_modifier", account_settings.bde_auth_role) - diff --git a/erpnext/patches/v5_0/update_item_and_description_again.py b/erpnext/patches/v5_0/update_item_and_description_again.py deleted file mode 100644 index 35dedcc072b..00000000000 --- a/erpnext/patches/v5_0/update_item_and_description_again.py +++ /dev/null @@ -1,50 +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.utils import cstr -import re - -def execute(): - item_details = frappe._dict() - for d in frappe.db.sql("select name, description from `tabItem`", as_dict=1): - description = cstr(d.description).strip() - new_desc = extract_description(description) - - item_details.setdefault(d.name, frappe._dict({ - "old_description": description, - "new_description": new_desc - })) - - - dt_list= ["Purchase Order Item","Supplier Quotation Item", "BOM", "BOM Explosion Item" , \ - "BOM Item", "Opportunity Item" , "Quotation Item" , "Sales Order Item" , "Delivery Note Item" , \ - "Material Request Item" , "Purchase Receipt Item" , "Stock Entry Detail"] - for dt in dt_list: - frappe.reload_doctype(dt) - records = frappe.db.sql("""select name, `{0}` as item_code, description from `tab{1}` - where description is not null and description like '%%]*\>".format(tag), "", desc) - - return desc diff --git a/erpnext/patches/v5_0/update_item_desc_in_invoice.py b/erpnext/patches/v5_0/update_item_desc_in_invoice.py deleted file mode 100644 index dba35d56938..00000000000 --- a/erpnext/patches/v5_0/update_item_desc_in_invoice.py +++ /dev/null @@ -1,52 +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.website.utils import find_first_image -from frappe.utils import cstr -import re - -def execute(): - item_details = frappe._dict() - for d in frappe.db.sql("select name, description, image from `tabItem`", as_dict=1): - description = cstr(d.description).strip() - item_details.setdefault(d.name, frappe._dict({ - "description": description, - "image": d.image - })) - - - dt_list= ["Sales Invoice Item","Purchase Invoice Item"] - for dt in dt_list: - frappe.reload_doctype(dt) - records = frappe.db.sql("""select name, item_code, description from `tab{0}` - where ifnull(item_code, '') != '' and description is not null """.format(dt), as_dict=1) - - count = 1 - for d in records: - if item_details.get(d.item_code) and cstr(d.description) == item_details.get(d.item_code).description: - desc = item_details.get(d.item_code).description - image = item_details.get(d.item_code).image - else: - desc, image = extract_image_and_description(cstr(d.description)) - - if not image: - item_detail = item_details.get(d.item_code) - if item_detail: - image = item_detail.image - - frappe.db.sql("""update `tab{0}` set description = %s, image = %s - where name = %s """.format(dt), (desc, image, d.name)) - - count += 1 - if count % 500 == 0: - frappe.db.commit() - - -def extract_image_and_description(data): - image_url = find_first_image(data) - desc = data - for tag in ("img", "table", "tr", "td"): - desc = re.sub("\]*\>".format(tag), "", desc) - return desc, image_url \ No newline at end of file diff --git a/erpnext/patches/v5_0/update_item_description_and_image.py b/erpnext/patches/v5_0/update_item_description_and_image.py deleted file mode 100644 index 75df39ee399..00000000000 --- a/erpnext/patches/v5_0/update_item_description_and_image.py +++ /dev/null @@ -1,54 +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.website.utils import find_first_image -from frappe.utils import cstr -import re - -def execute(): - item_details = frappe._dict() - for d in frappe.db.sql("select name, description_html, description from `tabItem`", as_dict=1): - description = cstr(d.description_html).strip() or cstr(d.description).strip() - image_url, new_desc = extract_image_and_description(description) - - item_details.setdefault(d.name, frappe._dict({ - "old_description": description, - "new_description": new_desc, - "image_url": image_url - })) - - - dt_list= ["Purchase Order Item","Supplier Quotation Item", "BOM", "BOM Explosion Item" , \ - "BOM Item", "Opportunity Item" , "Quotation Item" , "Sales Order Item" , "Delivery Note Item" , \ - "Material Request Item" , "Purchase Receipt Item" , "Stock Entry Detail"] - for dt in dt_list: - frappe.reload_doctype(dt) - records = frappe.db.sql("""select name, `{0}` as item_code, description from `tab{1}` - where description is not null and image is null and description like '%%]+\>", "", data) - - return image_url, desc diff --git a/erpnext/patches/v5_0/update_item_name_in_bom.py b/erpnext/patches/v5_0/update_item_name_in_bom.py deleted file mode 100644 index 5781542a2a3..00000000000 --- a/erpnext/patches/v5_0/update_item_name_in_bom.py +++ /dev/null @@ -1,18 +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 - -def execute(): - frappe.reload_doc("manufacturing", "doctype", "bom") - frappe.reload_doc("manufacturing", "doctype", "bom_item") - frappe.reload_doc("manufacturing", "doctype", "bom_explosion_item") - frappe.reload_doc("manufacturing", "doctype", "bom_operation") - - frappe.db.sql("""update `tabBOM` as bom set bom.item_name = \ - ( select item.item_name from `tabItem` as item where item.name = bom.item)""") - frappe.db.sql("""update `tabBOM Item` as bomItem set bomItem.item_name = ( select item.item_name \ - from `tabItem` as item where item.name = bomItem.item_code)""") - frappe.db.sql("""update `tabBOM Explosion Item` as explosionItem set explosionItem.item_name = \ - ( select item.item_name from `tabItem` as item where item.name = explosionItem.item_code)""") diff --git a/erpnext/patches/v5_0/update_journal_entry_title.py b/erpnext/patches/v5_0/update_journal_entry_title.py deleted file mode 100644 index eaa2be054fe..00000000000 --- a/erpnext/patches/v5_0/update_journal_entry_title.py +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doctype("Journal Entry") - frappe.db.sql("""update `tabJournal Entry` set title = - if(ifnull(pay_to_recd_from, "")!="", pay_to_recd_from, - (select account from `tabJournal Entry Account` - where parent=`tabJournal Entry`.name and idx=1 limit 1))""") diff --git a/erpnext/patches/v5_0/update_material_transfer_for_manufacture.py b/erpnext/patches/v5_0/update_material_transfer_for_manufacture.py deleted file mode 100644 index f31c9fed4dc..00000000000 --- a/erpnext/patches/v5_0/update_material_transfer_for_manufacture.py +++ /dev/null @@ -1,6 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.db.sql("""update `tabStock Entry` set purpose='Material Transfer for Manufacture' - where ifnull(work_order, '')!='' and purpose='Material Transfer'""") diff --git a/erpnext/patches/v5_0/update_material_transferred_for_manufacturing.py b/erpnext/patches/v5_0/update_material_transferred_for_manufacturing.py deleted file mode 100644 index 2a09aa29afd..00000000000 --- a/erpnext/patches/v5_0/update_material_transferred_for_manufacturing.py +++ /dev/null @@ -1,10 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doctype("Work Order") - frappe.db.sql("""update `tabWork Order` set material_transferred_for_manufacturing= - (select sum(fg_completed_qty) from `tabStock Entry` - where docstatus=1 - and work_order=`tabWork Order`.name - and purpose = "Material Transfer for Manufacture")""") diff --git a/erpnext/patches/v5_0/update_material_transferred_for_manufacturing_again.py b/erpnext/patches/v5_0/update_material_transferred_for_manufacturing_again.py deleted file mode 100644 index 5847c83d38f..00000000000 --- a/erpnext/patches/v5_0/update_material_transferred_for_manufacturing_again.py +++ /dev/null @@ -1,19 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - wo_order_qty_transferred = frappe._dict() - for se in frappe.db.sql("""select work_order, sum(fg_completed_qty) as transferred_qty - from `tabStock Entry` - where docstatus=1 and ifnull(work_order, '') != '' - and purpose = 'Material Transfer for Manufacture' - group by work_order""", as_dict=1): - wo_order_qty_transferred.setdefault(se.work_order, se.transferred_qty) - - for d in frappe.get_all("Work Order", filters={"docstatus": 1}, fields=["name", "qty"]): - if d.name in wo_order_qty_transferred: - material_transferred_for_manufacturing = wo_order_qty_transferred.get(d.name) \ - if wo_order_qty_transferred.get(d.name) <= d.qty else d.qty - - frappe.db.sql("""update `tabWork Order` set material_transferred_for_manufacturing=%s - where name=%s""", (material_transferred_for_manufacturing, d.name)) \ No newline at end of file diff --git a/erpnext/patches/v5_0/update_operation_description.py b/erpnext/patches/v5_0/update_operation_description.py deleted file mode 100644 index 4ce32f35f11..00000000000 --- a/erpnext/patches/v5_0/update_operation_description.py +++ /dev/null @@ -1,11 +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 -import frappe.permissions - -def execute(): - if "opn_description" in frappe.db.get_table_columns("BOM Operation"): - frappe.db.sql("""update `tabBOM Operation` set description = opn_description - where ifnull(description, '') = ''""") \ No newline at end of file diff --git a/erpnext/patches/v5_0/update_opportunity.py b/erpnext/patches/v5_0/update_opportunity.py deleted file mode 100644 index 8eb45c48e7e..00000000000 --- a/erpnext/patches/v5_0/update_opportunity.py +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doc('crm', 'doctype', 'opportunity') - frappe.reload_doc('crm', 'doctype', 'opportunity_item') - - # all existing opportunities were with items - frappe.db.sql("update `tabDocType` set module = 'CRM' where name='Opportunity Item'") - frappe.db.sql("update tabOpportunity set with_items=1, title=customer_name") - frappe.db.sql("update `tabEmail Account` set append_to='Opportunity' where append_to='Lead'") diff --git a/erpnext/patches/v5_0/update_projects.py b/erpnext/patches/v5_0/update_projects.py deleted file mode 100644 index 68e03c9bdb6..00000000000 --- a/erpnext/patches/v5_0/update_projects.py +++ /dev/null @@ -1,34 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals -import frappe - -def execute(): - # convert milestones to tasks - frappe.reload_doctype("Project") - frappe.reload_doc("projects", "doctype", "project_task") - frappe.reload_doctype("Task") - frappe.reload_doc("projects", "doctype", "task_depends_on") - frappe.reload_doc("projects", "doctype", "time_log") - - for m in frappe.get_all("Project Milestone", "*"): - if (m.milestone and m.milestone_date - and frappe.db.exists("Project", m.parent)): - subject = (m.milestone[:139] + "…") if (len(m.milestone) > 140) else m.milestone - description = m.milestone - task = frappe.get_doc({ - "doctype": "Task", - "subject": subject, - "description": description if description!=subject else None, - "expected_start_date": m.milestone_date, - "status": "Open" if m.status=="Pending" else "Closed", - "project": m.parent, - }) - task.flags.ignore_mandatory = True - task.insert(ignore_permissions=True) - - # remove project milestone - frappe.delete_doc("DocType", "Project Milestone") - - # remove calendar events for milestone - for e in frappe.get_all("Event", ["name"], {"ref_type": "Project"}): - frappe.delete_doc("Event", e.name) diff --git a/erpnext/patches/v5_0/update_sms_sender.py b/erpnext/patches/v5_0/update_sms_sender.py deleted file mode 100644 index 7ffc703c43b..00000000000 --- a/erpnext/patches/v5_0/update_sms_sender.py +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.db.set_value("SMS Settings", "SMS Settings", "sms_sender_name", - frappe.db.get_single_value("Global Defaults", "sms_sender_name")) diff --git a/erpnext/patches/v5_0/update_tax_amount_after_discount_in_purchase_cycle.py b/erpnext/patches/v5_0/update_tax_amount_after_discount_in_purchase_cycle.py deleted file mode 100644 index 53df9422b38..00000000000 --- a/erpnext/patches/v5_0/update_tax_amount_after_discount_in_purchase_cycle.py +++ /dev/null @@ -1,17 +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 - -def execute(): - frappe.db.sql(""" - update - `tabPurchase Taxes and Charges` - set - tax_amount_after_discount_amount = tax_amount, - base_tax_amount_after_discount_amount = base_tax_amount - where - ifnull(tax_amount_after_discount_amount, 0) = 0 - and ifnull(base_tax_amount_after_discount_amount, 0) = 0 - """) \ No newline at end of file diff --git a/erpnext/patches/v5_0/update_temporary_account.py b/erpnext/patches/v5_0/update_temporary_account.py deleted file mode 100644 index 078c8714fff..00000000000 --- a/erpnext/patches/v5_0/update_temporary_account.py +++ /dev/null @@ -1,9 +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 - -def execute(): - frappe.db.sql("""Update `tabAccount` set account_type = 'Temporary' - where account_name in ('Temporary Assets', 'Temporary Liabilities', 'Temporary Opening')""") \ No newline at end of file diff --git a/erpnext/patches/v5_0/update_time_log_title.py b/erpnext/patches/v5_0/update_time_log_title.py deleted file mode 100644 index 8263be00075..00000000000 --- a/erpnext/patches/v5_0/update_time_log_title.py +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doctype("Time Log") - for d in frappe.get_all("Time Log"): - time_log = frappe.get_doc("Time Log", d.name) - time_log.set_title() - frappe.db.set_value("Time Log", time_log.name, "title", time_log.title) diff --git a/erpnext/patches/v5_1/__init__.py b/erpnext/patches/v5_1/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/erpnext/patches/v5_1/default_bom.py b/erpnext/patches/v5_1/default_bom.py deleted file mode 100644 index 6484edd6039..00000000000 --- a/erpnext/patches/v5_1/default_bom.py +++ /dev/null @@ -1,7 +0,0 @@ -from __future__ import unicode_literals - -import frappe - -def execute(): - frappe.db.sql("""Update `tabItem` as item set default_bom = NULL where - not exists(select name from `tabBOM` as bom where item.default_bom = bom.name and bom.docstatus =1 )""") \ No newline at end of file diff --git a/erpnext/patches/v5_1/fix_against_account.py b/erpnext/patches/v5_1/fix_against_account.py deleted file mode 100644 index a62c15b7d19..00000000000 --- a/erpnext/patches/v5_1/fix_against_account.py +++ /dev/null @@ -1,37 +0,0 @@ -from __future__ import unicode_literals - -import frappe - -from erpnext.accounts.doctype.gl_entry.gl_entry import update_against_account - -def execute(): - from_date = "2015-05-01" - - for doc in frappe.get_all("Journal Entry", - filters={"creation": (">", from_date), "docstatus": "1"}): - - # update in gl_entry - update_against_account("Journal Entry", doc.name) - - # update in jv - doc = frappe.get_doc("Journal Entry", doc.name) - doc.set_against_account() - doc.db_update() - - for doc in frappe.get_all("Sales Invoice", - filters={"creation": (">", from_date), "docstatus": "1"}, - fields=["name", "customer"]): - - frappe.db.sql("""update `tabGL Entry` set against=%s - where voucher_type='Sales Invoice' and voucher_no=%s - and credit > 0 and ifnull(party, '')=''""", - (doc.customer, doc.name)) - - for doc in frappe.get_all("Purchase Invoice", - filters={"creation": (">", from_date), "docstatus": "1"}, - fields=["name", "supplier"]): - - frappe.db.sql("""update `tabGL Entry` set against=%s - where voucher_type='Purchase Invoice' and voucher_no=%s - and debit > 0 and ifnull(party, '')=''""", - (doc.supplier, doc.name)) diff --git a/erpnext/patches/v5_1/rename_roles.py b/erpnext/patches/v5_1/rename_roles.py deleted file mode 100644 index e19c22a6142..00000000000 --- a/erpnext/patches/v5_1/rename_roles.py +++ /dev/null @@ -1,10 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - if not frappe.db.exists("Role", "Stock User"): - frappe.rename_doc("Role", "Material User", "Stock User") - if not frappe.db.exists("Role", "Stock Manager"): - frappe.rename_doc("Role", "Material Manager", "Stock Manager") - if not frappe.db.exists("Role", "Item Manager"): - frappe.rename_doc("Role", "Material Master Manager", "Item Manager") diff --git a/erpnext/patches/v5_1/sales_bom_rename.py b/erpnext/patches/v5_1/sales_bom_rename.py deleted file mode 100644 index e06012f3e41..00000000000 --- a/erpnext/patches/v5_1/sales_bom_rename.py +++ /dev/null @@ -1,12 +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 - -def execute(): - tables = frappe.db.sql_list("show tables") - for old_dt, new_dt in [["Sales BOM Item", "Product Bundle Item"], - ["Sales BOM", "Product Bundle"]]: - if "tab"+new_dt not in tables: - frappe.rename_doc("DocType", old_dt, new_dt, force=True) diff --git a/erpnext/patches/v5_2/__init__.py b/erpnext/patches/v5_2/__init__.py deleted file mode 100644 index baffc488252..00000000000 --- a/erpnext/patches/v5_2/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from __future__ import unicode_literals diff --git a/erpnext/patches/v5_2/change_item_selects_to_checks.py b/erpnext/patches/v5_2/change_item_selects_to_checks.py deleted file mode 100644 index 1ee8f6caa57..00000000000 --- a/erpnext/patches/v5_2/change_item_selects_to_checks.py +++ /dev/null @@ -1,19 +0,0 @@ -from __future__ import unicode_literals - -import frappe - -def execute(): - fields = ("is_stock_item", "is_asset_item", "has_batch_no", "has_serial_no", - "is_sales_item", "is_purchase_item", "inspection_required", "is_sub_contracted_item") - - # convert to 1 or 0 - update_str = ", ".join(["`{0}`=if(`{0}`='Yes',1,0)".format(f) for f in fields]) - frappe.db.sql("update tabItem set {0}".format(update_str)) - - frappe.db.commit() - - # alter fields to int - for f in fields: - frappe.db.sql("alter table tabItem change {0} {0} int(1) default '0'".format(f, f)) - - frappe.reload_doctype("Item") diff --git a/erpnext/patches/v5_4/__init__.py b/erpnext/patches/v5_4/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/erpnext/patches/v5_4/cleanup_journal_entry.py b/erpnext/patches/v5_4/cleanup_journal_entry.py deleted file mode 100644 index 6860e6ad090..00000000000 --- a/erpnext/patches/v5_4/cleanup_journal_entry.py +++ /dev/null @@ -1,21 +0,0 @@ -from __future__ import unicode_literals -import frappe -from pymysql import InternalError - -def execute(): - frappe.reload_doctype("Journal Entry Account") - for doctype, fieldname in ( - ("Sales Order", "against_sales_order"), - ("Purchase Order", "against_purchase_order"), - ("Sales Invoice", "against_invoice"), - ("Purchase Invoice", "against_voucher"), - ("Journal Entry", "against_jv"), - ("Expense Claim", "against_expense_claim"), - ): - try: - frappe.db.sql("""update `tabJournal Entry Account` - set reference_type=%s, reference_name={0} where ifnull({0}, '') != '' - """.format(fieldname), doctype) - except InternalError: - # column not found - pass diff --git a/erpnext/patches/v5_4/fix_invoice_outstanding.py b/erpnext/patches/v5_4/fix_invoice_outstanding.py deleted file mode 100644 index 54a1da69ef5..00000000000 --- a/erpnext/patches/v5_4/fix_invoice_outstanding.py +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe -from erpnext.accounts.doctype.gl_entry.gl_entry import update_outstanding_amt - -def execute(): - frappe.reload_doctype("Sales Invoice") - return_entries = frappe.get_list("Sales Invoice", filters={"is_return": 1, "docstatus": 1}, - fields=["debit_to", "customer", "return_against"]) - for d in return_entries: - update_outstanding_amt(d.debit_to, "Customer", d.customer, "Sales Invoice", d.return_against) diff --git a/erpnext/patches/v5_4/fix_missing_item_images.py b/erpnext/patches/v5_4/fix_missing_item_images.py deleted file mode 100644 index c6fe57896fa..00000000000 --- a/erpnext/patches/v5_4/fix_missing_item_images.py +++ /dev/null @@ -1,126 +0,0 @@ -from __future__ import print_function, unicode_literals -import frappe -import os -from frappe.utils import get_files_path -from frappe.core.doctype.file.file import get_content_hash - -def execute(): - files_path = get_files_path() - - # get files that don't have attached_to_name but exist - unlinked_files = get_unlinked_files(files_path) - if not unlinked_files: - return - - fixed_files = fix_files_for_item(files_path, unlinked_files) - - # fix remaining files - for key, file_data in unlinked_files.items(): - if key not in fixed_files: - rename_and_set_content_hash(files_path, unlinked_files, key) - frappe.db.commit() - -def fix_files_for_item(files_path, unlinked_files): - fixed_files = [] - - # make a list of files/something and /files/something to check in child table's image column - file_urls = [key for key in unlinked_files.keys()] + ["/" + key for key in unlinked_files.keys()] - file_item_code = get_file_item_code(file_urls) - - for (file_url, item_code), children in file_item_code.items(): - new_file_url = "/files/{0}".format(unlinked_files[file_url]["file_name"]) - - for row in children: - # print file_url, new_file_url, item_code, row.doctype, row.name - - # replace image in these rows with the new file url - frappe.db.set_value(row.doctype, row.name, "image", new_file_url, update_modified=False) - - # set it as attachment of this item code - file_data = frappe.get_doc("File", unlinked_files[file_url]["file"]) - file_data.attached_to_doctype = "Item" - file_data.attached_to_name = item_code - file_data.flags.ignore_folder_validate = True - - try: - file_data.save() - except IOError: - print("File {0} does not exist".format(new_file_url)) - - # marking fix to prevent further errors - fixed_files.append(file_url) - - continue - - # set it as image in Item - if not frappe.db.get_value("Item", item_code, "image"): - frappe.db.set_value("Item", item_code, "image", new_file_url, update_modified=False) - - rename_and_set_content_hash(files_path, unlinked_files, file_url) - - fixed_files.append(file_url) - - # commit - frappe.db.commit() - - return fixed_files - -def rename_and_set_content_hash(files_path, unlinked_files, file_url): - # rename this file - old_filename = os.path.join(files_path, unlinked_files[file_url]["file"]) - new_filename = os.path.join(files_path, unlinked_files[file_url]["file_name"]) - - if not os.path.exists(new_filename): - os.rename(old_filename, new_filename) - - # set content hash if missing - file_data_name = unlinked_files[file_url]["file"] - if not frappe.db.get_value("File", file_data_name, "content_hash"): - with open(new_filename, "r") as f: - content_hash = get_content_hash(f.read()) - frappe.db.set_value("File", file_data_name, "content_hash", content_hash) - -def get_unlinked_files(files_path): - # find files that have the same name as a File doc - # and the file_name mentioned in that File doc doesn't exist - # and it isn't already attached to a doc - unlinked_files = {} - files = os.listdir(files_path) - for file in files: - if not frappe.db.exists("File", {"file_name": file}): - file_data = frappe.db.get_value("File", {"name": file}, - ["file_name", "attached_to_doctype", "attached_to_name"], as_dict=True) - - if (file_data - and file_data.file_name - and file_data.file_name not in files - and not file_data.attached_to_doctype - and not file_data.attached_to_name): - - file_data["file"] = file - unlinked_files["files/{0}".format(file)] = file_data - - return unlinked_files - -def get_file_item_code(file_urls): - # get a map of file_url, item_code and list of documents where file_url will need to be changed in image field - file_item_code = {} - - doctypes = frappe.db.sql_list("""select name from `tabDocType` dt - where istable=1 - and exists (select name from `tabDocField` df where df.parent=dt.name and df.fieldname='item_code') - and exists (select name from `tabDocField` df where df.parent=dt.name and df.fieldname='image')""") - - for doctype in doctypes: - result = frappe.db.sql("""select name, image, item_code, '{0}' as doctype from `tab{0}` - where image in ({1})""".format(doctype, ", ".join(["%s"]*len(file_urls))), - file_urls, as_dict=True) - - for r in result: - key = (r.image, r.item_code) - if key not in file_item_code: - file_item_code[key] = [] - - file_item_code[key].append(r) - - return file_item_code diff --git a/erpnext/patches/v5_4/fix_reserved_qty_and_sle_for_packed_items.py b/erpnext/patches/v5_4/fix_reserved_qty_and_sle_for_packed_items.py deleted file mode 100644 index 6eb3994c7c5..00000000000 --- a/erpnext/patches/v5_4/fix_reserved_qty_and_sle_for_packed_items.py +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe -from erpnext.stock.stock_balance import repost_actual_qty - -def execute(): - cancelled_invoices = frappe.db.sql_list("""select name from `tabSales Invoice` - where docstatus = 2 and ifnull(update_stock, 0) = 1""") - - if cancelled_invoices: - repost_for = frappe.db.sql("""select distinct item_code, warehouse from `tabStock Ledger Entry` - where voucher_type = 'Sales Invoice' and voucher_no in (%s)""" - % (', '.join(['%s']*len(cancelled_invoices))), tuple(cancelled_invoices)) - - frappe.db.sql("""delete from `tabStock Ledger Entry` - where voucher_type = 'Sales Invoice' and voucher_no in (%s)""" - % (', '.join(['%s']*len(cancelled_invoices))), tuple(cancelled_invoices)) - - for item_code, warehouse in repost_for: - repost_actual_qty(item_code, warehouse) \ No newline at end of file diff --git a/erpnext/patches/v5_4/notify_system_managers_regarding_wrong_tax_calculation.py b/erpnext/patches/v5_4/notify_system_managers_regarding_wrong_tax_calculation.py deleted file mode 100644 index ba311225bb1..00000000000 --- a/erpnext/patches/v5_4/notify_system_managers_regarding_wrong_tax_calculation.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import print_function, unicode_literals -import frappe -from frappe.email import sendmail_to_system_managers -from frappe.utils import get_link_to_form - -def execute(): - wrong_records = [] - for dt in ("Quotation", "Sales Order", "Delivery Note", "Sales Invoice", - "Purchase Order", "Purchase Receipt", "Purchase Invoice"): - records = frappe.db.sql_list("""select name from `tab{0}` - where apply_discount_on = 'Net Total' and ifnull(discount_amount, 0) != 0 - and modified >= '2015-02-17' and docstatus=1""".format(dt)) - - if records: - records = [get_link_to_form(dt, d) for d in records] - wrong_records.append([dt, records]) - - if wrong_records: - content = """Dear System Manager, - -Due to an error related to Discount Amount on Net Total, tax calculation might be wrong in the following records. We did not fix the tax amount automatically because it can corrupt the entries, so we request you to check these records and amend if you found the calculation wrong. - -Please check following Entries: - -%s - - -Regards, - -Administrator""" % "\n".join([(d[0] + ": " + ", ".join(d[1])) for d in wrong_records]) - try: - sendmail_to_system_managers("[Important] [ERPNext] Tax calculation might be wrong, please check.", content) - except: - pass - - print("="*50) - print(content) - print("="*50) \ No newline at end of file diff --git a/erpnext/patches/v5_4/set_root_and_report_type.py b/erpnext/patches/v5_4/set_root_and_report_type.py deleted file mode 100644 index 9147644da2e..00000000000 --- a/erpnext/patches/v5_4/set_root_and_report_type.py +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - roots = frappe.db.sql("""select lft, rgt, report_type, root_type - from `tabAccount` where ifnull(parent_account, '')=''""", as_dict=1) - for d in roots: - frappe.db.sql("update `tabAccount` set report_type=%s, root_type=%s where lft > %s and rgt < %s", - (d.report_type, d.root_type, d.lft, d.rgt)) \ No newline at end of file diff --git a/erpnext/patches/v5_4/stock_entry_additional_costs.py b/erpnext/patches/v5_4/stock_entry_additional_costs.py deleted file mode 100644 index 3a98deb918e..00000000000 --- a/erpnext/patches/v5_4/stock_entry_additional_costs.py +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright (c) 2015, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe -from frappe.utils import flt - -def execute(): - frappe.reload_doctype("Stock Entry") - frappe.reload_doctype("Stock Entry Detail") - frappe.reload_doctype("Landed Cost Taxes and Charges") - - stock_entry_db_columns = frappe.db.get_table_columns("Stock Entry") - if "additional_operating_cost" in stock_entry_db_columns: - operating_cost_fieldname = "additional_operating_cost" - elif "total_fixed_cost" in stock_entry_db_columns: - operating_cost_fieldname = "total_fixed_cost" - else: - return - - - frappe.db.sql("""update `tabStock Entry Detail` sed, `tabStock Entry` se - set sed.valuation_rate=sed.incoming_rate, sed.basic_rate=sed.incoming_rate, sed.basic_amount=sed.amount - where sed.parent = se.name - and (se.purpose not in ('Manufacture', 'Repack') or ifnull({0}, 0)=0) - """.format(operating_cost_fieldname)) - - - stock_entries = frappe.db.sql_list("""select name from `tabStock Entry` - where purpose in ('Manufacture', 'Repack') and ifnull({0}, 0)!=0 - and docstatus < 2""".format(operating_cost_fieldname)) - - for d in stock_entries: - stock_entry = frappe.get_doc("Stock Entry", d) - stock_entry.append("additional_costs", { - "description": "Additional Operating Cost", - "amount": stock_entry.get(operating_cost_fieldname) - }) - - number_of_fg_items = len([t.t_warehouse for t in stock_entry.get("items") if t.t_warehouse]) - - for d in stock_entry.get("items"): - d.valuation_rate = d.incoming_rate - - if d.bom_no or (d.t_warehouse and number_of_fg_items == 1): - d.additional_cost = stock_entry.get(operating_cost_fieldname) - - d.basic_rate = flt(d.valuation_rate) - flt(d.additional_cost) - d.basic_amount = flt(flt(d.basic_rate) *flt(d.transfer_qty), d.precision("basic_amount")) - - stock_entry.flags.ignore_validate = True - stock_entry.flags.ignore_validate_update_after_submit = True - stock_entry.save() diff --git a/erpnext/patches/v5_4/update_purchase_cost_against_project.py b/erpnext/patches/v5_4/update_purchase_cost_against_project.py deleted file mode 100644 index 1b917c83c4f..00000000000 --- a/erpnext/patches/v5_4/update_purchase_cost_against_project.py +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright (c) 2015, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - for p in frappe.get_all("Project"): - purchase_cost = frappe.db.sql("""select sum(ifnull(base_net_amount, 0)) - from `tabPurchase Invoice Item` where project = %s and docstatus=1""", p.name) - purchase_cost = purchase_cost and purchase_cost[0][0] or 0 - - frappe.db.set_value("Project", p.name, "total_purchase_cost", purchase_cost) \ No newline at end of file diff --git a/erpnext/patches/v5_7/__init__.py b/erpnext/patches/v5_7/__init__.py deleted file mode 100644 index baffc488252..00000000000 --- a/erpnext/patches/v5_7/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from __future__ import unicode_literals diff --git a/erpnext/patches/v5_7/item_template_attributes.py b/erpnext/patches/v5_7/item_template_attributes.py deleted file mode 100644 index 6aa81f79b29..00000000000 --- a/erpnext/patches/v5_7/item_template_attributes.py +++ /dev/null @@ -1,124 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import print_function, unicode_literals -import frappe -from frappe.exceptions import SQLError - -def execute(): - """ - Structure History: - 1. Item and Item Variant - 2. Item, Variant Attribute, Manage Variants and Manage Variant Items - 3. Item, Item Variant Attribute, Item Attribute and Item Attribute Type (latest) - """ - rename_and_reload_doctypes() - - variant_templates = frappe.get_all("Item", filters={"has_variants": 1}, limit_page_length=1) - if not variant_templates: - # database does not have items that have variants - # so no point in running the patch - return - - variant_attributes = frappe.get_all("Item Variant Attribute", fields=["*"], limit_page_length=1) - - if variant_attributes: - # manage variant patch is already applied - migrate_manage_variants() - - else: - # old structure based on "Item Variant" table - try: - migrate_item_variants() - - except SQLError: - print("`tabItem Variant` not found") - -def rename_and_reload_doctypes(): - if "tabVariant Attribute" in frappe.db.get_tables(): - frappe.rename_doc("DocType", "Variant Attribute", "Item Variant Attribute") - - frappe.reload_doctype("Item") - frappe.reload_doc("Stock", "DocType", "Item Variant Attribute") - frappe.reload_doc("Stock", "DocType", "Item Attribute Value") - frappe.reload_doc("Stock", "DocType", "Item Attribute") - -def migrate_manage_variants(): - item_attribute = {} - for d in frappe.db.sql("""select DISTINCT va.attribute, i.variant_of - from `tabItem Variant Attribute` va, `tabItem` i - where va.parent = i.name and ifnull(i.variant_of, '')!=''""", as_dict=1): - item_attribute.setdefault(d.variant_of, []).append({"attribute": d.attribute}) - - for item, attributes in item_attribute.items(): - template = frappe.get_doc("Item", item) - template.set('attributes', attributes) - template.save() - -# patch old style -def migrate_item_variants(): - for item in frappe.get_all("Item", filters={"has_variants": 1}): - all_variants = frappe.get_all("Item", filters={"variant_of": item.name}, fields=["name", "description"]) - item_attributes = frappe.db.sql("""select distinct item_attribute, item_attribute_value - from `tabItem Variant` where parent=%s""", item.name) - - if not item_attributes and not all_variants: - item = frappe.get_doc("Item", item.name) - item.has_variants = 0 - item.save() - continue - - attribute_value_options = {} - for attribute, value in item_attributes: - attribute_value_options.setdefault(attribute, []).append(value) - - possible_combinations = get_possible_combinations(attribute_value_options) - - for variant in all_variants: - for combination in possible_combinations: - match = True - for attribute, value in combination.items(): - if "{0}: {1}".format(attribute, value) not in variant.description: - match = False - break - - if match: - # found the right variant - save_attributes_in_variant(variant, combination) - break - - save_attributes_in_template(item, attribute_value_options) - - frappe.delete_doc("DocType", "Item Variant") - -def save_attributes_in_template(item, attribute_value_options): - # store attribute in Item Variant Attribute table for template - template = frappe.get_doc("Item", item) - template.set("attributes", [{"attribute": attribute} for attribute in attribute_value_options.keys()]) - template.save() - -def get_possible_combinations(attribute_value_options): - possible_combinations = [] - - for attribute, values in attribute_value_options.items(): - if not possible_combinations: - for v in values: - possible_combinations.append({attribute: v}) - - else: - for v in values: - for combination in possible_combinations: - combination[attribute] = v - - return possible_combinations - -def save_attributes_in_variant(variant, combination): - # add data into attributes table - variant_item = frappe.get_doc("Item", variant.name) - variant_item.set("attributes", []) - for attribute, value in combination.items(): - variant_item.append("attributes", { - "attribute": attribute, - "attribute_value": value - }) - variant_item.save() diff --git a/erpnext/patches/v5_8/__init__.py b/erpnext/patches/v5_8/__init__.py deleted file mode 100644 index baffc488252..00000000000 --- a/erpnext/patches/v5_8/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from __future__ import unicode_literals diff --git a/erpnext/patches/v5_8/add_credit_note_print_heading.py b/erpnext/patches/v5_8/add_credit_note_print_heading.py deleted file mode 100644 index 476cbc89560..00000000000 --- a/erpnext/patches/v5_8/add_credit_note_print_heading.py +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe -from frappe import _ - -def execute(): - for print_heading in (_("Credit Note"), _("Debit Note")): - if not frappe.db.exists("Print Heading", print_heading): - frappe.get_doc({ - "doctype": "Print Heading", - "print_heading": print_heading - }).insert() diff --git a/erpnext/patches/v5_8/tax_rule.py b/erpnext/patches/v5_8/tax_rule.py deleted file mode 100644 index 8da28ba4c96..00000000000 --- a/erpnext/patches/v5_8/tax_rule.py +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doc("accounts", "doctype", "tax_rule") - - customers = frappe.db.sql("""select name, default_taxes_and_charges from tabCustomer where - ifnull(default_taxes_and_charges, '') != '' """, as_dict=1) - - for d in customers: - if not frappe.db.sql("select name from `tabTax Rule` where customer=%s", d.name): - tr = frappe.new_doc("Tax Rule") - tr.tax_type = "Sales" - tr.customer = d.name - tr.sales_tax_template = d.default_taxes_and_charges - tr.save() - - - suppliers = frappe.db.sql("""select name, default_taxes_and_charges from tabSupplier where - ifnull(default_taxes_and_charges, '') != '' """, as_dict=1) - - for d in suppliers: - if not frappe.db.sql("select name from `tabTax Rule` where supplier=%s", d.name): - tr = frappe.new_doc("Tax Rule") - tr.tax_type = "Purchase" - tr.supplier = d.name - tr.purchase_tax_template = d.default_taxes_and_charges - tr.save() \ No newline at end of file diff --git a/erpnext/patches/v5_8/update_order_reference_in_return_entries.py b/erpnext/patches/v5_8/update_order_reference_in_return_entries.py deleted file mode 100644 index 503263834c0..00000000000 --- a/erpnext/patches/v5_8/update_order_reference_in_return_entries.py +++ /dev/null @@ -1,92 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doctype("Delivery Note") - frappe.reload_doctype("Sales Invoice") - frappe.reload_doctype("Purchase Receipt") - frappe.reload_doctype("Sales Order Item") - frappe.reload_doctype("Purchase Order Item") - frappe.reload_doctype("Purchase Order Item Supplied") - - # sales return - return_entries = list(frappe.db.sql(""" - select dn.name as name, dn_item.name as row_id, dn.return_against, - dn_item.item_code, "Delivery Note" as doctype - from `tabDelivery Note Item` dn_item, `tabDelivery Note` dn - where dn_item.parent=dn.name and dn.is_return=1 and dn.docstatus < 2 - """, as_dict=1)) - - return_entries += list(frappe.db.sql(""" - select si.name as name, si_item.name as row_id, si.return_against, - si_item.item_code, "Sales Invoice" as doctype, update_stock - from `tabSales Invoice Item` si_item, `tabSales Invoice` si - where si_item.parent=si.name and si.is_return=1 and si.docstatus < 2 - """, as_dict=1)) - - for d in return_entries: - ref_field = "against_sales_order" if d.doctype == "Delivery Note" else "sales_order" - order_details = frappe.db.sql(""" - select {ref_field} as sales_order, so_detail, - (select transaction_date from `tabSales Order` where name=item.{ref_field}) as sales_order_date - from `tab{doctype} Item` item - where - parent=%s - and item_code=%s - and ifnull(so_detail, '') !='' - order by sales_order_date DESC limit 1 - """.format(ref_field=ref_field, doctype=d.doctype), (d.return_against, d.item_code), as_dict=1) - - if order_details: - frappe.db.sql(""" - update `tab{doctype} Item` - set {ref_field}=%s, so_detail=%s - where name=%s - """.format(doctype=d.doctype, ref_field=ref_field), - (order_details[0].sales_order, order_details[0].so_detail, d.row_id)) - - if (d.doctype=="Sales Invoice" and d.update_stock) or d.doctype=="Delivery Note": - doc = frappe.get_doc(d.doctype, d.name) - doc.update_reserved_qty() - - if d.doctype=="Sales Invoice": - doc.status_updater = [] - doc.update_status_updater_args() - - doc.update_prevdoc_status() - - #-------------------------- - # purchase return - return_entries = frappe.db.sql(""" - select pr.name as name, pr_item.name as row_id, pr.return_against, pr_item.item_code - from `tabPurchase Receipt Item` pr_item, `tabPurchase Receipt` pr - where pr_item.parent=pr.name and pr.is_return=1 and pr.docstatus < 2 - """, as_dict=1) - - for d in return_entries: - order_details = frappe.db.sql(""" - select prevdoc_docname as purchase_order, prevdoc_detail_docname as po_detail, - (select transaction_date from `tabPurchase Order` where name=item.prevdoc_detail_docname) as purchase_order_date - from `tabPurchase Receipt Item` item - where - parent=%s - and item_code=%s - and ifnull(prevdoc_detail_docname, '') !='' - and ifnull(prevdoc_doctype, '') = 'Purchase Order' and ifnull(prevdoc_detail_docname, '') != '' - order by purchase_order_date DESC limit 1 - """, (d.return_against, d.item_code), as_dict=1) - - if order_details: - frappe.db.sql(""" - update `tabPurchase Receipt Item` - set prevdoc_doctype='Purchase Order', prevdoc_docname=%s, prevdoc_detail_docname=%s - where name=%s - """, (order_details[0].purchase_order, order_details[0].po_detail, d.row_id)) - - pr = frappe.get_doc("Purchase Receipt", d.name) - pr.update_ordered_and_reserved_qty() - pr.update_prevdoc_status() - diff --git a/erpnext/patches/v6_0/__init__.py b/erpnext/patches/v6_0/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/erpnext/patches/v6_0/default_activity_rate.py b/erpnext/patches/v6_0/default_activity_rate.py deleted file mode 100644 index cfbfb723bcd..00000000000 --- a/erpnext/patches/v6_0/default_activity_rate.py +++ /dev/null @@ -1,14 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doc("projects", "doctype", "activity_cost") - - for cost in frappe.db.get_list("Activity Cost", filters = {"employee": ""}, - fields = ("name", "activity_type", "costing_rate", "billing_rate")): - activity_type = frappe.get_doc("Activity Type", cost.activity_type) - activity_type.costing_rate = cost.costing_rate - activity_type.billing_rate = cost.billing_rate - activity_type.save() - - frappe.delete_doc("Activity Cost", cost.name) diff --git a/erpnext/patches/v6_0/fix_outstanding_amount.py b/erpnext/patches/v6_0/fix_outstanding_amount.py deleted file mode 100644 index 0de689074f3..00000000000 --- a/erpnext/patches/v6_0/fix_outstanding_amount.py +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe -from erpnext.accounts.doctype.gl_entry.gl_entry import update_outstanding_amt - -def execute(): - for dt, party_field, account_field in (("Sales Invoice", "customer", "debit_to"), - ("Purchase Invoice", "supplier", "credit_to")): - - wrong_invoices = frappe.db.sql("""select name, {0} as account from `tab{1}` - where docstatus=1 and ifnull({2}, '')=''""".format(account_field, dt, party_field)) - - for invoice, account in wrong_invoices: - update_outstanding_amt(account, party_field.title(), None, dt, invoice) \ No newline at end of file diff --git a/erpnext/patches/v6_0/fix_planned_qty.py b/erpnext/patches/v6_0/fix_planned_qty.py deleted file mode 100644 index cf7b429249d..00000000000 --- a/erpnext/patches/v6_0/fix_planned_qty.py +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe -from erpnext.stock.stock_balance import get_planned_qty, update_bin_qty - -def execute(): - for item_code, warehouse in frappe.db.sql("""select distinct production_item, fg_warehouse - from `tabWork Order`"""): - if frappe.db.exists("Item", item_code) and frappe.db.exists("Warehouse", warehouse): - update_bin_qty(item_code, warehouse, { - "planned_qty": get_planned_qty(item_code, warehouse) - }) diff --git a/erpnext/patches/v6_0/multi_currency.py b/erpnext/patches/v6_0/multi_currency.py deleted file mode 100644 index b4c37fc2530..00000000000 --- a/erpnext/patches/v6_0/multi_currency.py +++ /dev/null @@ -1,65 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - # Reload doctype - for dt in ("Account", "GL Entry", "Journal Entry", - "Journal Entry Account", "Sales Invoice", "Purchase Invoice", "Customer", "Supplier"): - frappe.reload_doctype(dt) - - company_list = frappe.get_all("Company", fields=["name", "default_currency", "default_receivable_account"]) - for company in company_list: - - # update currency in account and gl entry as per company currency - frappe.db.sql("""update `tabAccount` set account_currency = %s - where ifnull(account_currency, '') = '' and company=%s""", (company.default_currency, company.name)) - - # update newly introduced field's value in sales / purchase invoice - frappe.db.sql(""" - update - `tabSales Invoice` - set - base_paid_amount=paid_amount, - base_write_off_amount=write_off_amount, - party_account_currency=%s - where company=%s - """, (company.default_currency, company.name)) - - frappe.db.sql(""" - update - `tabPurchase Invoice` - set - base_write_off_amount=write_off_amount, - party_account_currency=%s - where company=%s - """, (company.default_currency, company.name)) - - # update exchange rate, debit/credit in account currency in Journal Entry - frappe.db.sql(""" - update `tabJournal Entry Account` jea - set exchange_rate=1, - debit_in_account_currency=debit, - credit_in_account_currency=credit, - account_type=(select account_type from `tabAccount` where name=jea.account) - """) - - frappe.db.sql(""" - update `tabJournal Entry Account` jea, `tabJournal Entry` je - set account_currency=%s - where jea.parent = je.name and je.company=%s - """, (company.default_currency, company.name)) - - # update debit/credit in account currency in GL Entry - frappe.db.sql(""" - update - `tabGL Entry` - set - debit_in_account_currency=debit, - credit_in_account_currency=credit, - account_currency=%s - where - company=%s - """, (company.default_currency, company.name)) diff --git a/erpnext/patches/v6_0/set_default_title.py b/erpnext/patches/v6_0/set_default_title.py deleted file mode 100644 index cceff3f480c..00000000000 --- a/erpnext/patches/v6_0/set_default_title.py +++ /dev/null @@ -1,36 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doctype("Quotation") - frappe.db.sql("""update tabQuotation set title = customer_name""") - - frappe.reload_doctype("Sales Order") - frappe.db.sql("""update `tabSales Order` set title = customer_name""") - - frappe.reload_doctype("Delivery Note") - frappe.db.sql("""update `tabDelivery Note` set title = customer_name""") - - frappe.reload_doctype("Material Request") - frappe.db.sql("""update `tabMaterial Request` set title = material_request_type""") - - frappe.reload_doctype("Supplier Quotation") - frappe.db.sql("""update `tabSupplier Quotation` set title = supplier_name""") - - frappe.reload_doctype("Purchase Order") - frappe.db.sql("""update `tabPurchase Order` set title = supplier_name""") - - frappe.reload_doctype("Purchase Receipt") - frappe.db.sql("""update `tabPurchase Receipt` set title = supplier_name""") - - frappe.reload_doctype("Purchase Invoice") - frappe.db.sql("""update `tabPurchase Invoice` set title = supplier_name""") - - frappe.reload_doctype("Stock Entry") - frappe.db.sql("""update `tabStock Entry` set title = purpose""") - - frappe.reload_doctype("Sales Invoice") - frappe.db.sql("""update `tabSales Invoice` set title = customer_name""") - - frappe.reload_doctype("Expense Claim") - frappe.db.sql("""update `tabExpense Claim` set title = employee_name""") diff --git a/erpnext/patches/v6_10/__init__.py b/erpnext/patches/v6_10/__init__.py deleted file mode 100644 index baffc488252..00000000000 --- a/erpnext/patches/v6_10/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from __future__ import unicode_literals diff --git a/erpnext/patches/v6_10/email_digest_default_quote.py b/erpnext/patches/v6_10/email_digest_default_quote.py deleted file mode 100644 index 6139f1a88a6..00000000000 --- a/erpnext/patches/v6_10/email_digest_default_quote.py +++ /dev/null @@ -1,6 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doctype("Email Digest") - frappe.db.sql("update `tabEmail Digest` set add_quote = 1") diff --git a/erpnext/patches/v6_10/fix_billed_amount_in_drop_ship_po.py b/erpnext/patches/v6_10/fix_billed_amount_in_drop_ship_po.py deleted file mode 100644 index d7f72b58808..00000000000 --- a/erpnext/patches/v6_10/fix_billed_amount_in_drop_ship_po.py +++ /dev/null @@ -1,18 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.db.sql("""update `tabPurchase Order Item` set billed_amt = 0 - where delivered_by_supplier=1 and docstatus=1""") - - drop_ship_pos = frappe.db.sql("""select distinct parent from `tabPurchase Order Item` - where delivered_by_supplier=1 and docstatus=1""") - - for po in drop_ship_pos: - invoices = frappe.db.sql("""select distinct parent from `tabPurchase Invoice Item` - where purchase_order=%s and docstatus=1""", po[0]) - if invoices: - for inv in invoices: - frappe.get_doc("Purchase Invoice", inv[0]).update_qty(update_modified=False) - else: - frappe.db.sql("""update `tabPurchase Order` set per_billed=0 where name=%s""", po[0]) \ No newline at end of file diff --git a/erpnext/patches/v6_10/fix_delivery_status_of_drop_ship_item.py b/erpnext/patches/v6_10/fix_delivery_status_of_drop_ship_item.py deleted file mode 100644 index 9a53b7f5d39..00000000000 --- a/erpnext/patches/v6_10/fix_delivery_status_of_drop_ship_item.py +++ /dev/null @@ -1,10 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doctype("Sales Order Item") - for so_name in frappe.db.sql("""select distinct parent from `tabSales Order Item` - where delivered_by_supplier=1 and docstatus=1"""): - so = frappe.get_doc("Sales Order", so_name[0]) - so.update_delivery_status() - so.set_status(update=True, update_modified=False) \ No newline at end of file diff --git a/erpnext/patches/v6_10/fix_jv_total_amount.py b/erpnext/patches/v6_10/fix_jv_total_amount.py deleted file mode 100644 index 42cb9e9e150..00000000000 --- a/erpnext/patches/v6_10/fix_jv_total_amount.py +++ /dev/null @@ -1,14 +0,0 @@ -from __future__ import unicode_literals -import frappe - -# patch all for-print field (total amount) in Journal Entry in 2015 -def execute(): - for je in frappe.get_all("Journal Entry", filters={"creation": (">", "2015-01-01")}): - je = frappe.get_doc("Journal Entry", je.name) - original = je.total_amount - - je.set_print_format_fields() - - if je.total_amount != original: - je.db_set("total_amount", je.total_amount, update_modified=False) - je.db_set("total_amount_in_words", je.total_amount_in_words, update_modified=False) diff --git a/erpnext/patches/v6_10/fix_ordered_received_billed.py b/erpnext/patches/v6_10/fix_ordered_received_billed.py deleted file mode 100644 index c81a20ec545..00000000000 --- a/erpnext/patches/v6_10/fix_ordered_received_billed.py +++ /dev/null @@ -1,17 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - not_null_patch_date = frappe.db.sql("""select date(creation) from `tabPatch Log` where patch='frappe.patches.v6_9.int_float_not_null'""") - if not not_null_patch_date: - return - - not_null_patch_date = not_null_patch_date[0][0] - - for doctype in ("Purchase Invoice", "Sales Invoice", "Purchase Order", "Delivery Note", "Installation Note", "Delivery Note", "Purchase Receipt"): - for name in frappe.db.sql_list("""select name from `tab{doctype}` - where docstatus > 0 and (date(creation) >= %(patch_date)s or date(modified) >= %(patch_date)s)""".format(doctype=doctype), - {"patch_date": not_null_patch_date}): - - doc = frappe.get_doc(doctype, name) - doc.update_qty(update_modified=False) diff --git a/erpnext/patches/v6_12/__init__.py b/erpnext/patches/v6_12/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/erpnext/patches/v6_12/repost_entries_with_target_warehouse.py b/erpnext/patches/v6_12/repost_entries_with_target_warehouse.py deleted file mode 100644 index fb5eab4e057..00000000000 --- a/erpnext/patches/v6_12/repost_entries_with_target_warehouse.py +++ /dev/null @@ -1,175 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import print_function, unicode_literals -import frappe - -""" -This patch is written to fix Stock Ledger Entries and GL Entries -against Delivery Notes and Sales Invoice where Target Warehouse has been set wrongly -due to User Permissions on Warehouse. - -This cannot be run automatically because we can't take a call that -Target Warehouse has been set purposefully or by mistake. -Thats why we left it to the users to take the call, and manually run the patch. - -This patch has 2 main functions, `check()` and `repost()`. -- Run `check` function, to list out all the Sales Orders, Delivery Notes - and Sales Invoice with Target Warehouse. -- Run `repost` function to remove the Target Warehouse value and repost SLE and GLE again. - -To execute this patch run following commands from frappe-bench directory: -``` - bench --site [your-site-name] execute erpnext.patches.v6_12.repost_entries_with_target_warehouse.check - bench --site [your-site-name] backup - bench --site [your-site-name] execute erpnext.patches.v6_12.repost_entries_with_target_warehouse.repost -``` - -Exception Handling: -While reposting, if you get any exception, it will printed on screen. -Mostly it can be due to negative stock issue. If that is the case, follow these steps - - Ensure that stock is available for those items in the mentioned warehouse on the date mentioned in the error - - Execute `repost` funciton again -""" - -def check(): - so_list = get_affected_sales_order() - dn_list = get_affected_delivery_notes() - si_list = get_affected_sales_invoice() - - if so_list or dn_list or si_list: - print("Entries with Target Warehouse:") - - if so_list: - print("Sales Order") - print(so_list) - - if dn_list: - print("Delivery Notes") - print([d.name for d in dn_list]) - - if si_list: - print("Sales Invoice") - print([d.name for d in si_list]) - - -def repost(): - dn_failed_list, si_failed_list = [], [] - repost_dn(dn_failed_list) - repost_si(si_failed_list) - repost_so() - frappe.db.commit() - - if dn_failed_list: - print("-"*40) - print("Delivery Note Failed to Repost") - print(dn_failed_list) - - if si_failed_list: - print("-"*40) - print("Sales Invoice Failed to Repost") - print(si_failed_list) - print() - - print(""" -If above Delivery Notes / Sales Invoice failed due to negative stock, follow these steps: - - Ensure that stock is available for those items in the mentioned warehouse on the date mentioned in the error - - Run this patch again -""") - -def repost_dn(dn_failed_list): - dn_list = get_affected_delivery_notes() - - if dn_list: - print("-"*40) - print("Reposting Delivery Notes") - - for dn in dn_list: - if dn.docstatus == 0: - continue - - print(dn.name) - - try: - dn_doc = frappe.get_doc("Delivery Note", dn.name) - dn_doc.docstatus = 2 - dn_doc.update_prevdoc_status() - dn_doc.update_stock_ledger() - dn_doc.cancel_packing_slips() - frappe.db.sql("""delete from `tabGL Entry` - where voucher_type='Delivery Note' and voucher_no=%s""", dn.name) - - frappe.db.sql("update `tabDelivery Note Item` set target_warehouse='' where parent=%s", dn.name) - dn_doc = frappe.get_doc("Delivery Note", dn.name) - dn_doc.docstatus = 1 - dn_doc.on_submit() - frappe.db.commit() - except Exception: - dn_failed_list.append(dn.name) - frappe.local.stockledger_exceptions = None - print(frappe.get_traceback()) - frappe.db.rollback() - - frappe.db.sql("update `tabDelivery Note Item` set target_warehouse='' where docstatus=0") - -def repost_si(si_failed_list): - si_list = get_affected_sales_invoice() - - if si_list: - print("-"*40) - print("Reposting Sales Invoice") - - for si in si_list: - if si.docstatus == 0: - continue - - print(si.name) - - try: - si_doc = frappe.get_doc("Sales Invoice", si.name) - si_doc.docstatus = 2 - si_doc.update_stock_ledger() - frappe.db.sql("""delete from `tabGL Entry` - where voucher_type='Sales Invoice' and voucher_no=%s""", si.name) - - frappe.db.sql("update `tabSales Invoice Item` set target_warehouse='' where parent=%s", si.name) - si_doc = frappe.get_doc("Sales Invoice", si.name) - si_doc.docstatus = 1 - si_doc.update_stock_ledger() - si_doc.make_gl_entries() - frappe.db.commit() - except Exception: - si_failed_list.append(si.name) - frappe.local.stockledger_exceptions = None - print(frappe.get_traceback()) - frappe.db.rollback() - - frappe.db.sql("update `tabSales Invoice Item` set target_warehouse='' where docstatus=0") - -def repost_so(): - so_list = get_affected_sales_order() - - frappe.db.sql("update `tabSales Order Item` set target_warehouse=''") - - if so_list: - print("-"*40) - print("Sales Order reposted") - - -def get_affected_delivery_notes(): - return frappe.db.sql("""select distinct dn.name, dn.docstatus - from `tabDelivery Note` dn, `tabDelivery Note Item` dn_item - where dn.name=dn_item.parent and dn.docstatus < 2 - and dn_item.target_warehouse is not null and dn_item.target_warehouse != '' - order by dn.posting_date asc""", as_dict=1) - -def get_affected_sales_invoice(): - return frappe.db.sql("""select distinct si.name, si.docstatus - from `tabSales Invoice` si, `tabSales Invoice Item` si_item - where si.name=si_item.parent and si.docstatus < 2 and si.update_stock=1 - and si_item.target_warehouse is not null and si_item.target_warehouse != '' - order by si.posting_date asc""", as_dict=1) - -def get_affected_sales_order(): - return frappe.db.sql_list("""select distinct parent from `tabSales Order Item` - where target_warehouse is not null and target_warehouse != '' and docstatus <2""") \ No newline at end of file diff --git a/erpnext/patches/v6_12/set_overdue_tasks.py b/erpnext/patches/v6_12/set_overdue_tasks.py deleted file mode 100644 index 7dbb8ba8b6b..00000000000 --- a/erpnext/patches/v6_12/set_overdue_tasks.py +++ /dev/null @@ -1,8 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doctype("Task") - - from erpnext.projects.doctype.task.task import set_tasks_as_overdue - set_tasks_as_overdue() diff --git a/erpnext/patches/v6_16/__init__.py b/erpnext/patches/v6_16/__init__.py deleted file mode 100644 index baffc488252..00000000000 --- a/erpnext/patches/v6_16/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from __future__ import unicode_literals diff --git a/erpnext/patches/v6_16/create_manufacturer_records.py b/erpnext/patches/v6_16/create_manufacturer_records.py deleted file mode 100644 index 5ae65f06609..00000000000 --- a/erpnext/patches/v6_16/create_manufacturer_records.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe -from frappe.utils import cstr - -def execute(): - frappe.reload_doc("stock", "doctype", "manufacturer") - frappe.reload_doctype("Item") - - for d in frappe.db.sql("""select distinct manufacturer from tabItem - where ifnull(manufacturer, '') != '' and disabled=0"""): - manufacturer_name = cstr(d[0]).strip() - if manufacturer_name and not frappe.db.exists("Manufacturer", manufacturer_name): - man = frappe.new_doc("Manufacturer") - man.short_name = manufacturer_name - man.full_name = manufacturer_name - man.save() diff --git a/erpnext/patches/v6_16/update_billing_status_in_dn_and_pr.py b/erpnext/patches/v6_16/update_billing_status_in_dn_and_pr.py deleted file mode 100644 index 481f13005ba..00000000000 --- a/erpnext/patches/v6_16/update_billing_status_in_dn_and_pr.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - for dt in ("Delivery Note", "Purchase Receipt"): - frappe.reload_doctype(dt) - frappe.reload_doctype(dt + " Item") - - # Update billed_amt in DN and PR which are not against any order - for d in frappe.db.sql("""select name from `tabDelivery Note Item` item - where (so_detail is null or so_detail = '') and docstatus=1""", as_dict=1): - - billed_amt = frappe.db.sql("""select sum(amount) from `tabSales Invoice Item` - where dn_detail=%s and docstatus=1""", d.name) - billed_amt = billed_amt and billed_amt[0][0] or 0 - frappe.db.set_value("Delivery Note Item", d.name, "billed_amt", billed_amt, update_modified=False) - - frappe.db.commit() - - # Update billed_amt in DN and PR which are not against any order - for d in frappe.db.sql("""select name from `tabPurchase Receipt Item` item - where (purchase_order_item is null or purchase_order_item = '') and docstatus=1""", as_dict=1): - - billed_amt = frappe.db.sql("""select sum(amount) from `tabPurchase Invoice Item` - where pr_detail=%s and docstatus=1""", d.name) - billed_amt = billed_amt and billed_amt[0][0] or 0 - frappe.db.set_value("Purchase Receipt Item", d.name, "billed_amt", billed_amt, update_modified=False) - - frappe.db.commit() - - for dt in ("Delivery Note", "Purchase Receipt"): - # Update billed amt which are against order or invoice - # Update billing status for all - for d in frappe.db.sql("select name from `tab{0}` where docstatus=1".format(dt), as_dict=1): - doc = frappe.get_doc(dt, d.name) - doc.update_billing_status(update_modified=False) - doc.set_status(update=True, update_modified=False) - - frappe.db.commit() diff --git a/erpnext/patches/v6_19/__init__.py b/erpnext/patches/v6_19/__init__.py deleted file mode 100644 index baffc488252..00000000000 --- a/erpnext/patches/v6_19/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from __future__ import unicode_literals diff --git a/erpnext/patches/v6_19/comment_feed_communication.py b/erpnext/patches/v6_19/comment_feed_communication.py deleted file mode 100644 index bc41c2d8ffe..00000000000 --- a/erpnext/patches/v6_19/comment_feed_communication.py +++ /dev/null @@ -1,7 +0,0 @@ -from __future__ import unicode_literals -import frappe -from frappe.patches.v6_19.comment_feed_communication import update_timeline_doc_for - -def execute(): - for doctype in ("Customer", "Supplier", "Employee", "Project"): - update_timeline_doc_for(doctype) diff --git a/erpnext/patches/v6_2/__init__.py b/erpnext/patches/v6_2/__init__.py deleted file mode 100644 index baffc488252..00000000000 --- a/erpnext/patches/v6_2/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from __future__ import unicode_literals diff --git a/erpnext/patches/v6_2/fix_missing_default_taxes_and_lead.py b/erpnext/patches/v6_2/fix_missing_default_taxes_and_lead.py deleted file mode 100644 index b0cfc3d3bf9..00000000000 --- a/erpnext/patches/v6_2/fix_missing_default_taxes_and_lead.py +++ /dev/null @@ -1,25 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - # remove missing lead - for customer in frappe.db.sql_list("""select name from `tabCustomer` - where ifnull(lead_name, '')!='' and not exists (select name from `tabLead` where name=`tabCustomer`.lead_name)"""): - frappe.db.set_value("Customer", customer, "lead_name", None) - - # remove missing default taxes - for customer in frappe.db.sql_list("""select name from `tabCustomer` - where ifnull(default_taxes_and_charges, '')!='' and not exists ( - select name from `tabSales Taxes and Charges Template` where name=`tabCustomer`.default_taxes_and_charges - )"""): - c = frappe.get_doc("Customer", customer) - c.default_taxes_and_charges = None - c.save() - - for supplier in frappe.db.sql_list("""select name from `tabSupplier` - where ifnull(default_taxes_and_charges, '')!='' and not exists ( - select name from `tabPurchase Taxes and Charges Template` where name=`tabSupplier`.default_taxes_and_charges - )"""): - c = frappe.get_doc("Supplier", supplier) - c.default_taxes_and_charges = None - c.save() diff --git a/erpnext/patches/v6_2/remove_newsletter_duplicates.py b/erpnext/patches/v6_2/remove_newsletter_duplicates.py deleted file mode 100644 index f9d15475d17..00000000000 --- a/erpnext/patches/v6_2/remove_newsletter_duplicates.py +++ /dev/null @@ -1,13 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - duplicates = frappe.db.sql("""select email_group, email, count(name) - from `tabEmail Group Member` - group by email_group, email - having count(name) > 1""") - - # delete all duplicates except 1 - for email_group, email, count in duplicates: - frappe.db.sql("""delete from `tabEmail Group Member` - where email_group=%s and email=%s limit %s""", (email_group, email, count-1)) diff --git a/erpnext/patches/v6_20/__init__.py b/erpnext/patches/v6_20/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/erpnext/patches/v6_20/set_party_account_currency_in_orders.py b/erpnext/patches/v6_20/set_party_account_currency_in_orders.py deleted file mode 100644 index ae7ad9592df..00000000000 --- a/erpnext/patches/v6_20/set_party_account_currency_in_orders.py +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - for doctype in ("Sales Order", "Purchase Order"): - frappe.reload_doctype(doctype) - - for order in frappe.db.sql("""select name, {0} as party from `tab{1}` - where advance_paid > 0 and docstatus=1""" - .format(("customer" if doctype=="Sales Order" else "supplier"), doctype), as_dict=1): - - party_account_currency = frappe.db.get_value("Journal Entry Account", { - "reference_type": doctype, - "reference_name": order.name, - "party": order.party, - "docstatus": 1, - "is_advance": "Yes" - }, "account_currency") - - frappe.db.set_value(doctype, order.name, "party_account_currency", party_account_currency) - \ No newline at end of file diff --git a/erpnext/patches/v6_20x/__init__.py b/erpnext/patches/v6_20x/__init__.py deleted file mode 100644 index baffc488252..00000000000 --- a/erpnext/patches/v6_20x/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from __future__ import unicode_literals diff --git a/erpnext/patches/v6_20x/remove_customer_supplier_roles.py b/erpnext/patches/v6_20x/remove_customer_supplier_roles.py deleted file mode 100644 index a6515768876..00000000000 --- a/erpnext/patches/v6_20x/remove_customer_supplier_roles.py +++ /dev/null @@ -1,23 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doc("buying", "doctype", "request_for_quotation_supplier") - frappe.reload_doc("buying", "doctype", "request_for_quotation_item") - frappe.reload_doc("buying", "doctype", "request_for_quotation") - frappe.reload_doc("projects", "doctype", "timesheet") - - for role in ('Customer', 'Supplier'): - frappe.db.sql('''delete from `tabHas Role` - where role=%s and parent in ("Administrator", "Guest")''', role) - - if not frappe.db.sql('select name from `tabHas Role` where role=%s', role): - - # delete DocPerm - for doctype in frappe.db.sql('select parent from tabDocPerm where role=%s', role): - d = frappe.get_doc("DocType", doctype[0]) - d.permissions = [p for p in d.permissions if p.role != role] - d.save() - - # delete Role - frappe.delete_doc_if_exists('Role', role) diff --git a/erpnext/patches/v6_20x/remove_fiscal_year_from_holiday_list.py b/erpnext/patches/v6_20x/remove_fiscal_year_from_holiday_list.py deleted file mode 100644 index d440c6859e3..00000000000 --- a/erpnext/patches/v6_20x/remove_fiscal_year_from_holiday_list.py +++ /dev/null @@ -1,19 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doctype("Holiday List") - - default_holiday_list = frappe.db.get_value("Holiday List", {"is_default": 1}) - if default_holiday_list: - for company in frappe.get_all("Company", fields=["name", "default_holiday_list"]): - if not company.default_holiday_list: - frappe.db.set_value("Company", company.name, "default_holiday_list", default_holiday_list) - - - fiscal_years = frappe._dict((fy.name, fy) for fy in frappe.get_all("Fiscal Year", fields=["name", "year_start_date", "year_end_date"])) - - for holiday_list in frappe.get_all("Holiday List", fields=["name", "fiscal_year"]): - fy = fiscal_years[holiday_list.fiscal_year] - frappe.db.set_value("Holiday List", holiday_list.name, "from_date", fy.year_start_date) - frappe.db.set_value("Holiday List", holiday_list.name, "to_date", fy.year_end_date) diff --git a/erpnext/patches/v6_20x/rename_project_name_to_project.py b/erpnext/patches/v6_20x/rename_project_name_to_project.py deleted file mode 100644 index 49ec9d22bc0..00000000000 --- a/erpnext/patches/v6_20x/rename_project_name_to_project.py +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe -from frappe.model.utils.rename_field import rename_field - -def execute(): - - doc_list = ["Work Order", "BOM", "Purchase Invoice Item", "Sales Invoice", - "Purchase Order Item", "Stock Entry", "Delivery Note", "Sales Order", - "Purchase Receipt Item", "Supplier Quotation Item"] - - for doctype in doc_list: - frappe.reload_doctype(doctype) - rename_field(doctype, "project_name", "project") - \ No newline at end of file diff --git a/erpnext/patches/v6_20x/repost_valuation_rate_for_negative_inventory.py b/erpnext/patches/v6_20x/repost_valuation_rate_for_negative_inventory.py deleted file mode 100644 index 8369fea3179..00000000000 --- a/erpnext/patches/v6_20x/repost_valuation_rate_for_negative_inventory.py +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe -from frappe.utils import cint -from erpnext.stock.stock_balance import repost - -def execute(): - if cint(frappe.db.get_value("Stock Settings", None, "allow_negative_stock")): - repost(only_actual=True) \ No newline at end of file diff --git a/erpnext/patches/v6_20x/set_compact_print.py b/erpnext/patches/v6_20x/set_compact_print.py deleted file mode 100644 index 495407f0e08..00000000000 --- a/erpnext/patches/v6_20x/set_compact_print.py +++ /dev/null @@ -1,8 +0,0 @@ -from __future__ import unicode_literals -import frappe - -from erpnext.setup.install import create_compact_item_print_custom_field - -def execute(): - create_compact_item_print_custom_field() - frappe.db.set_value("Print Settings", None, "compact_item_print", 1) diff --git a/erpnext/patches/v6_20x/update_product_bundle_description.py b/erpnext/patches/v6_20x/update_product_bundle_description.py deleted file mode 100644 index 1fac44b0010..00000000000 --- a/erpnext/patches/v6_20x/update_product_bundle_description.py +++ /dev/null @@ -1,11 +0,0 @@ -from __future__ import unicode_literals -import frappe -from frappe.utils import sanitize_html - -def execute(): - for product_bundle in frappe.get_all('Product Bundle'): - doc = frappe.get_doc('Product Bundle', product_bundle.name) - for item in doc.items: - if item.description: - description = sanitize_html(item.description) - item.db_set('description', description, update_modified=False) diff --git a/erpnext/patches/v6_21/__init__.py b/erpnext/patches/v6_21/__init__.py deleted file mode 100644 index baffc488252..00000000000 --- a/erpnext/patches/v6_21/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from __future__ import unicode_literals diff --git a/erpnext/patches/v6_21/fix_reorder_level.py b/erpnext/patches/v6_21/fix_reorder_level.py deleted file mode 100644 index 82a35ebab17..00000000000 --- a/erpnext/patches/v6_21/fix_reorder_level.py +++ /dev/null @@ -1,24 +0,0 @@ -from __future__ import unicode_literals - -import frappe -from erpnext.stock.doctype.item.item import DuplicateReorderRows - -def execute(): - if frappe.db.has_column("Item", "re_order_level"): - for item in frappe.db.sql("""select name, default_warehouse, re_order_level, re_order_qty - from tabItem - where ifnull(re_order_level, 0) != 0 - and ifnull(re_order_qty, 0) != 0""", as_dict=1): - - item_doc = frappe.get_doc("Item", item.name) - item_doc.append("reorder_levels", { - "warehouse": item.default_warehouse, - "warehouse_reorder_level": item.re_order_level, - "warehouse_reorder_qty": item.re_order_qty, - "material_request_type": "Purchase" - }) - - try: - item_doc.save() - except DuplicateReorderRows: - pass diff --git a/erpnext/patches/v6_21/rename_material_request_fields.py b/erpnext/patches/v6_21/rename_material_request_fields.py deleted file mode 100644 index 07be27a5d6d..00000000000 --- a/erpnext/patches/v6_21/rename_material_request_fields.py +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe -from frappe.model.utils.rename_field import rename_field - -def execute(): - frappe.reload_doc('stock', 'doctype', 'material_request_item') - rename_field("Material Request Item", "sales_order_no", "sales_order") - - frappe.reload_doc('support', 'doctype', 'maintenance_schedule_item') - rename_field("Maintenance Schedule Item", "prevdoc_docname", "sales_order") - \ No newline at end of file diff --git a/erpnext/patches/v6_23/__init__.py b/erpnext/patches/v6_23/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/erpnext/patches/v6_23/update_stopped_status_to_closed.py b/erpnext/patches/v6_23/update_stopped_status_to_closed.py deleted file mode 100644 index 79d1e0ac300..00000000000 --- a/erpnext/patches/v6_23/update_stopped_status_to_closed.py +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - for dt in ("Sales Order", "Purchase Order"): - frappe.db.sql("update `tab{0}` set status='Closed' where status='Stopped'".format(dt)) \ No newline at end of file diff --git a/erpnext/patches/v6_24/__init__.py b/erpnext/patches/v6_24/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/erpnext/patches/v6_24/map_customer_address_to_shipping_address_on_po.py b/erpnext/patches/v6_24/map_customer_address_to_shipping_address_on_po.py deleted file mode 100644 index 1dd8083c7c3..00000000000 --- a/erpnext/patches/v6_24/map_customer_address_to_shipping_address_on_po.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doctype("Purchase Order") - - if not frappe.db.has_column("Purchase Order", "shipping_address"): - return - - if not frappe.db.has_column("Purchase Order", "customer_address"): - return - - frappe.db.sql("""update `tabPurchase Order` set shipping_address=customer_address, - shipping_address_display=customer_address_display""") - - frappe.db.commit() \ No newline at end of file diff --git a/erpnext/patches/v6_24/set_recurring_id.py b/erpnext/patches/v6_24/set_recurring_id.py deleted file mode 100644 index 527a2fd3d97..00000000000 --- a/erpnext/patches/v6_24/set_recurring_id.py +++ /dev/null @@ -1,13 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - for doctype in ('Sales Order', 'Purchase Order', 'Sales Invoice', - 'Purchase Invoice'): - frappe.reload_doctype(doctype) - frappe.db.sql('''update `tab{0}` set submit_on_creation=1, notify_by_email=1 - where is_recurring=1'''.format(doctype)) - frappe.db.sql('''update `tab{0}` set notify_by_email=1 - where is_recurring=1'''.format(doctype)) - frappe.db.sql('''update `tab{0}` set recurring_id = name - where is_recurring=1 and ifnull(recurring_id, '') = "" '''.format(doctype)) diff --git a/erpnext/patches/v6_27/__init__.py b/erpnext/patches/v6_27/__init__.py deleted file mode 100644 index baffc488252..00000000000 --- a/erpnext/patches/v6_27/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from __future__ import unicode_literals diff --git a/erpnext/patches/v6_27/fix_recurring_order_status.py b/erpnext/patches/v6_27/fix_recurring_order_status.py deleted file mode 100644 index 5843c9fbe5f..00000000000 --- a/erpnext/patches/v6_27/fix_recurring_order_status.py +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - for doc in ( - { - "doctype": "Sales Order", - "stock_doctype": "Delivery Note", - "invoice_doctype": "Sales Invoice", - "stock_doctype_ref_field": "against_sales_order", - "invoice_ref_field": "sales_order", - "qty_field": "delivered_qty" - }, - { - "doctype": "Purchase Order", - "stock_doctype": "Purchase Receipt", - "invoice_doctype": "Purchase Invoice", - "stock_doctype_ref_field": "prevdoc_docname", - "invoice_ref_field": "purchase_order", - "qty_field": "received_qty" - }): - - order_list = frappe.db.sql("""select name from `tab{0}` - where docstatus=1 and is_recurring=1 - and ifnull(recurring_id, '') != name and creation >= '2016-01-25'""" - .format(doc["doctype"]), as_dict=1) - - for order in order_list: - frappe.db.sql("""update `tab{0} Item` - set {1}=0, billed_amt=0 where parent=%s""".format(doc["doctype"], - doc["qty_field"]), order.name) - - # Check against Delivery Note and Purchase Receipt - stock_doc_list = frappe.db.sql("""select distinct parent from `tab{0} Item` - where docstatus=1 and ifnull({1}, '')=%s""" - .format(doc["stock_doctype"], doc["stock_doctype_ref_field"]), order.name) - - if stock_doc_list: - for dn in stock_doc_list: - frappe.get_doc(doc["stock_doctype"], dn[0]).update_qty(update_modified=False) - - # Check against Invoice - invoice_list = frappe.db.sql("""select distinct parent from `tab{0} Item` - where docstatus=1 and ifnull({1}, '')=%s""" - .format(doc["invoice_doctype"], doc["invoice_ref_field"]), order.name) - - if invoice_list: - for dn in invoice_list: - frappe.get_doc(doc["invoice_doctype"], dn[0]).update_qty(update_modified=False) - - frappe.get_doc(doc["doctype"], order.name).set_status(update=True, update_modified=False) \ No newline at end of file diff --git a/erpnext/patches/v6_3/__init__.py b/erpnext/patches/v6_3/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/erpnext/patches/v6_3/convert_applicable_territory.py b/erpnext/patches/v6_3/convert_applicable_territory.py deleted file mode 100644 index 231a483ea22..00000000000 --- a/erpnext/patches/v6_3/convert_applicable_territory.py +++ /dev/null @@ -1,24 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doc("stock", "doctype", "price_list_country") - frappe.reload_doc("accounts", "doctype", "shipping_rule_country") - frappe.reload_doctype("Price List") - frappe.reload_doctype("Shipping Rule") - frappe.reload_doctype("shopping_cart", "doctype", "shopping_cart_settings") - - # for price list - countries = frappe.db.sql_list("select name from tabCountry") - - for doctype in ("Price List", "Shipping Rule"): - for at in frappe.db.sql("""select name, parent, territory from `tabApplicable Territory` where - parenttype = %s """, doctype, as_dict=True): - if at.territory in countries: - parent = frappe.get_doc(doctype, at.parent) - if not parent.countries: - parent.append("countries", {"country": at.territory}) - parent.save() - - - frappe.delete_doc("DocType", "Applicable Territory") diff --git a/erpnext/patches/v6_4/__init__.py b/erpnext/patches/v6_4/__init__.py deleted file mode 100644 index baffc488252..00000000000 --- a/erpnext/patches/v6_4/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from __future__ import unicode_literals diff --git a/erpnext/patches/v6_4/email_digest_update.py b/erpnext/patches/v6_4/email_digest_update.py deleted file mode 100644 index 8342b7fce61..00000000000 --- a/erpnext/patches/v6_4/email_digest_update.py +++ /dev/null @@ -1,10 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doctype("Email Digest") - frappe.db.sql("""update `tabEmail Digest` set expense_year_to_date = - income_year_to_date""") - - if frappe.db.exists("Email Digest", "Scheduler Errors"): - frappe.delete_doc("Email Digest", "Scheduler Errors") diff --git a/erpnext/patches/v6_4/fix_duplicate_bins.py b/erpnext/patches/v6_4/fix_duplicate_bins.py deleted file mode 100644 index 77d05273e8e..00000000000 --- a/erpnext/patches/v6_4/fix_duplicate_bins.py +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe -from erpnext.stock.stock_balance import repost_stock - -def execute(): - bins = frappe.db.sql("""select item_code, warehouse, count(*) from `tabBin` - group by item_code, warehouse having count(*) > 1""", as_dict=True) - - for d in bins: - try: - frappe.db.sql("delete from tabBin where item_code=%s and warehouse=%s", (d.item_code, d.warehouse)) - - repost_stock(d.item_code, d.warehouse, allow_zero_rate=True, only_actual=False, only_bin=True) - - frappe.db.commit() - except: - frappe.db.rollback() \ No newline at end of file diff --git a/erpnext/patches/v6_4/fix_expense_included_in_valuation.py b/erpnext/patches/v6_4/fix_expense_included_in_valuation.py deleted file mode 100644 index 7ed15ab010e..00000000000 --- a/erpnext/patches/v6_4/fix_expense_included_in_valuation.py +++ /dev/null @@ -1,74 +0,0 @@ -# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import print_function, unicode_literals -import frappe -from frappe.utils import cstr - -def execute(): - for company in frappe.db.sql("select name, expenses_included_in_valuation from tabCompany", as_dict=1): - frozen_date = get_frozen_date(company.name, company.expenses_included_in_valuation) - - # Purchase Invoices after frozen date - # which are not against Receipt, but valuation related tax is there - pi_list = frappe.db.sql(""" - select distinct pi.name - from `tabPurchase Invoice` pi, `tabPurchase Invoice Item` pi_item - where - pi.name = pi_item.parent - and pi.company = %s - and pi.posting_date > %s - and pi.docstatus = 1 - and pi.is_opening = 'No' - and (pi_item.item_tax_amount is not null and pi_item.item_tax_amount > 0) - and (pi_item.purchase_receipt is null or pi_item.purchase_receipt = '') - and (pi_item.item_code is not null and pi_item.item_code != '') - and exists(select name from `tabItem` where name=pi_item.item_code and is_stock_item=1) - """, (company.name, frozen_date), as_dict=1) - - for pi in pi_list: - # Check whether gle exists for Expenses Included in Valuation account against the PI - gle_for_expenses_included_in_valuation = frappe.db.sql("""select name from `tabGL Entry` - where voucher_type='Purchase Invoice' and voucher_no=%s and account=%s""", - (pi.name, company.expenses_included_in_valuation)) - - if gle_for_expenses_included_in_valuation: - print(pi.name) - - frappe.db.sql("""delete from `tabGL Entry` - where voucher_type='Purchase Invoice' and voucher_no=%s""", pi.name) - - purchase_invoice = frappe.get_doc("Purchase Invoice", pi.name) - - # some old entries have missing expense accounts - if purchase_invoice.against_expense_account: - expense_account = purchase_invoice.against_expense_account.split(",") - if len(expense_account) == 1: - expense_account = expense_account[0] - for item in purchase_invoice.items: - if not item.expense_account: - item.db_set("expense_account", expense_account, update_modified=False) - - purchase_invoice.make_gl_entries() - -def get_frozen_date(company, account): - # Accounting frozen upto - accounts_frozen_upto = frappe.db.get_single_value("Accounts Settings", "acc_frozen_upto") - - # Last adjustment entry to correct Expenses Included in Valuation account balance - last_adjustment_entry = frappe.db.sql("""select posting_date from `tabGL Entry` - where account=%s and company=%s and voucher_type = 'Journal Entry' - order by posting_date desc limit 1""", (account, company)) - - last_adjustment_date = cstr(last_adjustment_entry[0][0]) if last_adjustment_entry else None - - # Last period closing voucher - last_closing_entry = frappe.db.sql("""select posting_date from `tabGL Entry` - where company=%s and voucher_type = 'Period Closing Voucher' - order by posting_date desc limit 1""", company) - - last_closing_date = cstr(last_closing_entry[0][0]) if last_closing_entry else None - - frozen_date = max([accounts_frozen_upto, last_adjustment_date, last_closing_date]) - - return frozen_date or '1900-01-01' diff --git a/erpnext/patches/v6_4/fix_journal_entries_due_to_reconciliation.py b/erpnext/patches/v6_4/fix_journal_entries_due_to_reconciliation.py deleted file mode 100644 index b53412d7ebb..00000000000 --- a/erpnext/patches/v6_4/fix_journal_entries_due_to_reconciliation.py +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import print_function, unicode_literals -import frappe - -def execute(): - frappe.reload_doctype("Sales Invoice Advance") - frappe.reload_doctype("Purchase Invoice Advance") - - je_rows = frappe.db.sql(""" - select name, parent, reference_type, reference_name, debit, credit - from `tabJournal Entry Account` - where docstatus=1 and date(modified) >= '2015-09-17' - and ((ifnull(debit_in_account_currency, 0)*exchange_rate != ifnull(debit, 0)) - or (ifnull(credit_in_account_currency, 0)*exchange_rate != ifnull(credit, 0))) - order by parent - """, as_dict=True) - - journal_entries = [] - - for d in je_rows: - if d.parent not in journal_entries: - journal_entries.append(d.parent) - - is_advance_entry=None - if d.reference_type in ("Sales Invoice", "Purchase Invoice") and d.reference_name: - is_advance_entry = frappe.db.sql("""select name from `tab{0}` - where reference_name=%s and reference_row=%s - and ifnull(allocated_amount, 0) > 0 and docstatus=1""" - .format(d.reference_type + " Advance"), (d.parent, d.name)) - - if is_advance_entry or not (d.debit or d.credit): - frappe.db.sql(""" - update `tabJournal Entry Account` - set debit=debit_in_account_currency*exchange_rate, - credit=credit_in_account_currency*exchange_rate - where name=%s""", d.name) - else: - frappe.db.sql(""" - update `tabJournal Entry Account` - set debit_in_account_currency=debit/exchange_rate, - credit_in_account_currency=credit/exchange_rate - where name=%s""", d.name) - - for d in journal_entries: - print(d) - # delete existing gle - frappe.db.sql("delete from `tabGL Entry` where voucher_type='Journal Entry' and voucher_no=%s", d) - - # repost gl entries - je = frappe.get_doc("Journal Entry", d) - je.make_gl_entries() \ No newline at end of file diff --git a/erpnext/patches/v6_4/fix_modified_in_sales_order_and_purchase_order.py b/erpnext/patches/v6_4/fix_modified_in_sales_order_and_purchase_order.py deleted file mode 100644 index f27489e7b01..00000000000 --- a/erpnext/patches/v6_4/fix_modified_in_sales_order_and_purchase_order.py +++ /dev/null @@ -1,10 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - for doctype in ("Sales Order", "Purchase Order"): - data = frappe.db.sql("""select parent, modified_by, modified - from `tab{doctype} Item` where docstatus=1 group by parent""".format(doctype=doctype), as_dict=True) - for item in data: - frappe.db.sql("""update `tab{doctype}` set modified_by=%(modified_by)s, modified=%(modified)s - where name=%(parent)s""".format(doctype=doctype), item) diff --git a/erpnext/patches/v6_4/fix_sales_order_maintenance_status.py b/erpnext/patches/v6_4/fix_sales_order_maintenance_status.py deleted file mode 100644 index 50aa9e542e4..00000000000 --- a/erpnext/patches/v6_4/fix_sales_order_maintenance_status.py +++ /dev/null @@ -1,8 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - for doc in frappe.get_all("Sales Order", filters={"docstatus": 1, - "order_type": "Maintenance"}): - doc = frappe.get_doc("Sales Order", doc.name) - doc.set_status(update=True) diff --git a/erpnext/patches/v6_4/fix_status_in_sales_and_purchase_order.py b/erpnext/patches/v6_4/fix_status_in_sales_and_purchase_order.py deleted file mode 100644 index 746a99004af..00000000000 --- a/erpnext/patches/v6_4/fix_status_in_sales_and_purchase_order.py +++ /dev/null @@ -1,8 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - for doctype in ("Sales Order", "Purchase Order"): - for doc in frappe.get_all(doctype, filters={"docstatus": 1}): - doc = frappe.get_doc(doctype, doc.name) - doc.set_status(update=True) diff --git a/erpnext/patches/v6_4/make_image_thumbnail.py b/erpnext/patches/v6_4/make_image_thumbnail.py deleted file mode 100644 index 2c86e8af864..00000000000 --- a/erpnext/patches/v6_4/make_image_thumbnail.py +++ /dev/null @@ -1,15 +0,0 @@ -from __future__ import print_function, unicode_literals -import frappe - -def execute(): - frappe.reload_doctype("File") - frappe.reload_doctype("Item") - for item in frappe.get_all("Item", fields=("name", "website_image", "thumbnail")): - if item.website_image and not item.thumbnail: - item_doc = frappe.get_doc("Item", item.name) - try: - item_doc.make_thumbnail() - if item_doc.thumbnail: - item_doc.db_set("thumbnail", item_doc.thumbnail, update_modified=False) - except Exception: - print("Unable to make thumbnail for {0}".format(item.website_image.encode("utf-8"))) diff --git a/erpnext/patches/v6_4/repost_gle_for_journal_entries_where_reference_name_missing.py b/erpnext/patches/v6_4/repost_gle_for_journal_entries_where_reference_name_missing.py deleted file mode 100644 index 1319b535588..00000000000 --- a/erpnext/patches/v6_4/repost_gle_for_journal_entries_where_reference_name_missing.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import print_function, unicode_literals -import frappe - -def execute(): - je_list = frappe.db.sql_list("""select distinct parent from `tabJournal Entry Account` je - where docstatus=1 and ifnull(reference_name, '') !='' and creation > '2015-03-01' - and not exists(select name from `tabGL Entry` - where voucher_type='Journal Entry' and voucher_no=je.parent - and against_voucher_type=je.reference_type - and against_voucher=je.reference_name)""") - - for d in je_list: - print(d) - - # delete existing gle - frappe.db.sql("delete from `tabGL Entry` where voucher_type='Journal Entry' and voucher_no=%s", d) - - # repost gl entries - je = frappe.get_doc("Journal Entry", d) - je.make_gl_entries() \ No newline at end of file diff --git a/erpnext/patches/v6_4/round_status_updater_percentages.py b/erpnext/patches/v6_4/round_status_updater_percentages.py deleted file mode 100644 index 900e906b7bd..00000000000 --- a/erpnext/patches/v6_4/round_status_updater_percentages.py +++ /dev/null @@ -1,14 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - for doctype, fieldname in ( - ("Sales Order", "per_billed"), - ("Sales Order", "per_delivered"), - ("Delivery Note", "per_installed"), - ("Purchase Order", "per_billed"), - ("Purchase Order", "per_received"), - ("Material Request", "per_ordered"), - ): - frappe.db.sql("""update `tab{doctype}` set `{fieldname}`=round(`{fieldname}`, 2)""".format( - doctype=doctype, fieldname=fieldname)) diff --git a/erpnext/patches/v6_4/set_user_in_contact.py b/erpnext/patches/v6_4/set_user_in_contact.py deleted file mode 100644 index 7e8a6eecd57..00000000000 --- a/erpnext/patches/v6_4/set_user_in_contact.py +++ /dev/null @@ -1,7 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doctype("Contact") - frappe.db.sql("""update tabContact, tabUser set tabContact.user = tabUser.name - where tabContact.email_id = tabUser.email""") diff --git a/erpnext/patches/v6_5/__init__.py b/erpnext/patches/v6_5/__init__.py deleted file mode 100644 index baffc488252..00000000000 --- a/erpnext/patches/v6_5/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from __future__ import unicode_literals diff --git a/erpnext/patches/v6_5/show_in_website_for_template_item.py b/erpnext/patches/v6_5/show_in_website_for_template_item.py deleted file mode 100644 index af6e8304d67..00000000000 --- a/erpnext/patches/v6_5/show_in_website_for_template_item.py +++ /dev/null @@ -1,15 +0,0 @@ -from __future__ import unicode_literals -import frappe -import frappe.website.render - -def execute(): - for item_code in frappe.db.sql_list("""select distinct variant_of from `tabItem` - where variant_of is not null and variant_of !='' and show_in_website=1"""): - - item = frappe.get_doc("Item", item_code) - item.db_set("show_in_website", 1, update_modified=False) - - item.make_route() - item.db_set("route", item.route, update_modified=False) - - frappe.website.render.clear_cache() diff --git a/erpnext/patches/v6_6/__init__.py b/erpnext/patches/v6_6/__init__.py deleted file mode 100644 index baffc488252..00000000000 --- a/erpnext/patches/v6_6/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from __future__ import unicode_literals diff --git a/erpnext/patches/v6_6/fix_website_image.py b/erpnext/patches/v6_6/fix_website_image.py deleted file mode 100644 index cc3e2d852c4..00000000000 --- a/erpnext/patches/v6_6/fix_website_image.py +++ /dev/null @@ -1,32 +0,0 @@ -from __future__ import print_function, unicode_literals -import frappe -from frappe.utils import encode - -def execute(): - """Fix the File records created via item.py even if the website_image file didn't exist""" - for item in frappe.db.sql_list("""select name from `tabItem` - where website_image is not null and website_image != '' - and website_image like '/files/%' - and exists ( - select name from `tabFile` - where attached_to_doctype='Item' - and attached_to_name=`tabItem`.name - and file_url=`tabItem`.website_image - and (file_name is null or file_name = '') - )"""): - - item = frappe.get_doc("Item", item) - file = frappe.get_doc("File", { - "attached_to_doctype": "Item", - "attached_to_name": item.name, - "file_url": item.website_image - }) - - try: - file.validate_file() - except IOError: - print(encode(item.website_image), "does not exist") - file.delete() - item.db_set("website_image", None, update_modified=False) - - diff --git a/erpnext/patches/v6_6/remove_fiscal_year_from_leave_allocation.py b/erpnext/patches/v6_6/remove_fiscal_year_from_leave_allocation.py deleted file mode 100644 index 11c582fc493..00000000000 --- a/erpnext/patches/v6_6/remove_fiscal_year_from_leave_allocation.py +++ /dev/null @@ -1,17 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doctype("Leave Allocation") - if frappe.db.has_column("Leave Allocation", "fiscal_year"): - for leave_allocation in frappe.db.sql("select name, fiscal_year from `tabLeave Allocation`", as_dict=True): - dates = frappe.db.get_value("Fiscal Year", leave_allocation["fiscal_year"], - ["year_start_date", "year_end_date"]) - - if dates: - year_start_date, year_end_date = dates - - frappe.db.sql("""update `tabLeave Allocation` - set from_date=%s, to_date=%s where name=%s""", - (year_start_date, year_end_date, leave_allocation["name"])) - diff --git a/erpnext/patches/v6_8/__init__.py b/erpnext/patches/v6_8/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/erpnext/patches/v6_8/make_webform_standard.py b/erpnext/patches/v6_8/make_webform_standard.py deleted file mode 100644 index 2cc16a286f8..00000000000 --- a/erpnext/patches/v6_8/make_webform_standard.py +++ /dev/null @@ -1,14 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - pass - - # done via fixtures - - # frappe.reload_doctype("Web Form") - # frappe.delete_doc("Web Form", "Issues") - # frappe.delete_doc("Web Form", "Addresses") - - # from erpnext.setup.install import add_web_forms - # add_web_forms() diff --git a/erpnext/patches/v6_8/move_drop_ship_to_po_items.py b/erpnext/patches/v6_8/move_drop_ship_to_po_items.py deleted file mode 100644 index 7184deecccc..00000000000 --- a/erpnext/patches/v6_8/move_drop_ship_to_po_items.py +++ /dev/null @@ -1,43 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doctype("Purchase Order") - frappe.reload_doctype("Purchase Order Item") - - if not frappe.db.has_column("Purchase Order", "delivered_by_supplier"): - return - - for po in frappe.get_all("Purchase Order", filters={"delivered_by_supplier": 1}, fields=["name"]): - purchase_order = frappe.get_doc("Purchase Order", po) - - for item in purchase_order.items: - if item.prevdoc_doctype == "Sales Order": - delivered_by_supplier = frappe.get_value("Sales Order Item", item.prevdoc_detail_docname, - "delivered_by_supplier") - - if delivered_by_supplier: - frappe.db.sql("""update `tabPurchase Order Item` - set delivered_by_supplier=1, billed_amt=amount, received_qty=qty - where name=%s """, item.name) - - update_per_received(purchase_order) - update_per_billed(purchase_order) - -def update_per_received(po): - frappe.db.sql(""" update `tabPurchase Order` - set per_received = round((select sum(if(qty > ifnull(received_qty, 0), - ifnull(received_qty, 0), qty)) / sum(qty) *100 - from `tabPurchase Order Item` - where parent = %(name)s), 2) - where name = %(name)s """, {"name": po.name}) - -def update_per_billed(po): - frappe.db.sql(""" update `tabPurchase Order` - set per_billed = round((select sum( if(amount > ifnull(billed_amt, 0), - ifnull(billed_amt, 0), amount)) / sum(amount) *100 - from `tabPurchase Order Item` - where parent = %(name)s), 2) - where name = %(name)s """, {"name": po.name}) - - diff --git a/erpnext/patches/v7_0/__init__.py b/erpnext/patches/v7_0/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/erpnext/patches/v7_0/calculate_total_costing_amount.py b/erpnext/patches/v7_0/calculate_total_costing_amount.py deleted file mode 100644 index 8ed60a29550..00000000000 --- a/erpnext/patches/v7_0/calculate_total_costing_amount.py +++ /dev/null @@ -1,18 +0,0 @@ -from __future__ import unicode_literals -import frappe -from frappe.utils import flt - -def execute(): - frappe.reload_doc('projects', 'doctype', 'timesheet') - - for data in frappe.get_all('Timesheet', fields=["name, total_costing_amount"], - filters = [["docstatus", "<", "2"]]): - if flt(data.total_costing_amount) == 0.0: - ts = frappe.get_doc('Timesheet', data.name) - ts.update_cost() - ts.calculate_total_amounts() - ts.flags.ignore_validate = True - ts.flags.ignore_mandatory = True - ts.flags.ignore_validate_update_after_submit = True - ts.flags.ignore_links = True - ts.save() diff --git a/erpnext/patches/v7_0/convert_timelog_to_timesheet.py b/erpnext/patches/v7_0/convert_timelog_to_timesheet.py deleted file mode 100644 index 8c60b5b71ec..00000000000 --- a/erpnext/patches/v7_0/convert_timelog_to_timesheet.py +++ /dev/null @@ -1,69 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doc('projects', 'doctype', 'task') - frappe.reload_doc('projects', 'doctype', 'timesheet') - if not frappe.db.table_exists("Time Log"): - return - - from erpnext.manufacturing.doctype.work_order.work_order \ - import make_timesheet, add_timesheet_detail - - for data in frappe.db.sql("select * from `tabTime Log`", as_dict=1): - if data.task: - company = frappe.db.get_value("Task", data.task, "company") - elif data.work_order: - company = frappe.db.get_value("Work Order", data.work_order, "company") - else: - company = frappe.db.get_single_value('Global Defaults', 'default_company') - - time_sheet = make_timesheet(data.work_order, company) - args = get_timelog_data(data) - add_timesheet_detail(time_sheet, args) - if data.docstatus == 2: - time_sheet.docstatus = 0 - else: - time_sheet.docstatus = data.docstatus - time_sheet.employee = data.employee - time_sheet.note = data.note - time_sheet.company = company - - time_sheet.set_status() - time_sheet.set_dates() - time_sheet.update_cost() - time_sheet.calculate_total_amounts() - time_sheet.flags.ignore_validate = True - time_sheet.flags.ignore_links = True - time_sheet.save(ignore_permissions=True) - - # To ignore validate_mandatory_fields function - if data.docstatus == 1: - time_sheet.db_set("docstatus", 1) - for d in time_sheet.get("time_logs"): - d.db_set("docstatus", 1) - time_sheet.update_work_order(time_sheet.name) - time_sheet.update_task_and_project() - if data.docstatus == 2: - time_sheet.db_set("docstatus", 2) - for d in time_sheet.get("time_logs"): - d.db_set("docstatus", 2) - -def get_timelog_data(data): - return { - 'is_billable': data.billable, - 'from_time': data.from_time, - 'hours': data.hours, - 'to_time': data.to_time, - 'project': data.project, - 'task': data.task, - 'activity_type': data.activity_type, - 'operation': data.operation, - 'operation_id': data.operation_id, - 'workstation': data.workstation, - 'completed_qty': data.completed_qty, - 'billing_rate': data.billing_rate, - 'billing_amount': data.billing_amount, - 'costing_rate': data.costing_rate, - 'costing_amount': data.costing_amount - } diff --git a/erpnext/patches/v7_0/convert_timelogbatch_to_timesheet.py b/erpnext/patches/v7_0/convert_timelogbatch_to_timesheet.py deleted file mode 100644 index e78f163e077..00000000000 --- a/erpnext/patches/v7_0/convert_timelogbatch_to_timesheet.py +++ /dev/null @@ -1,32 +0,0 @@ -from __future__ import unicode_literals -import frappe -from frappe.utils import cint - -def execute(): - if not frappe.db.exists("DocType", "Time Log Batch"): - return - - from erpnext.manufacturing.doctype.work_order.work_order import add_timesheet_detail - - for tlb in frappe.get_all('Time Log Batch', fields=["*"], - filters = [["docstatus", "<", "2"]]): - time_sheet = frappe.new_doc('Timesheet') - time_sheet.employee= "" - time_sheet.company = frappe.db.get_single_value('Global Defaults', 'default_company') - time_sheet.sales_invoice = tlb.sales_invoice - - for data in frappe.get_all('Time Log Batch Detail', fields=["*"], - filters = {'parent': tlb.name}): - args = get_timesheet_data(data) - add_timesheet_detail(time_sheet, args) - - time_sheet.docstatus = tlb.docstatus - time_sheet.flags.ignore_links = True - time_sheet.save(ignore_permissions=True) - -def get_timesheet_data(data): - from erpnext.patches.v7_0.convert_timelog_to_timesheet import get_timelog_data - - time_log = frappe.get_all('Time Log', fields=["*"], filters = {'name': data.time_log}) - if time_log: - return get_timelog_data(time_log[0]) \ No newline at end of file diff --git a/erpnext/patches/v7_0/create_budget_record.py b/erpnext/patches/v7_0/create_budget_record.py deleted file mode 100644 index fd8bec9f327..00000000000 --- a/erpnext/patches/v7_0/create_budget_record.py +++ /dev/null @@ -1,57 +0,0 @@ -from __future__ import unicode_literals -import frappe - -from erpnext.accounts.doctype.budget.budget import DuplicateBudgetError - -def execute(): - frappe.reload_doc("accounts", "doctype", "budget") - frappe.reload_doc("accounts", "doctype", "budget_account") - - existing_budgets = frappe.db.sql(""" - select - cc.name, cc.company, cc.distribution_id, - budget.account, budget.budget_allocated, budget.fiscal_year - from - `tabCost Center` cc, `tabBudget Detail` budget - where - cc.name=budget.parent - """, as_dict=1) - - actions = {} - for d in frappe.db.sql("select name, yearly_bgt_flag, monthly_bgt_flag from tabCompany", as_dict=1): - actions.setdefault(d.name, d) - - budget_records = [] - for d in existing_budgets: - budget = frappe.db.get_value("Budget", - {"cost_center": d.name, "fiscal_year": d.fiscal_year, "company": d.company}) - - if not budget: - budget = frappe.new_doc("Budget") - budget.cost_center = d.name - budget.fiscal_year = d.fiscal_year - budget.monthly_distribution = d.distribution_id - budget.company = d.company - if actions[d.company]["yearly_bgt_flag"]: - budget.action_if_annual_budget_exceeded = actions[d.company]["yearly_bgt_flag"] - if actions[d.company]["monthly_bgt_flag"]: - budget.action_if_accumulated_monthly_budget_exceeded = actions[d.company]["monthly_bgt_flag"] - else: - budget = frappe.get_doc("Budget", budget) - - budget.append("accounts", { - "account": d.account, - "budget_amount": d.budget_allocated - }) - - try: - budget.insert() - budget_records.append(budget) - except DuplicateBudgetError: - pass - - for budget in budget_records: - budget.submit() - - if frappe.db.get_value("DocType", "Budget Detail"): - frappe.delete_doc("DocType", "Budget Detail") \ No newline at end of file diff --git a/erpnext/patches/v7_0/create_warehouse_nestedset.py b/erpnext/patches/v7_0/create_warehouse_nestedset.py deleted file mode 100644 index 1c9fc32142c..00000000000 --- a/erpnext/patches/v7_0/create_warehouse_nestedset.py +++ /dev/null @@ -1,128 +0,0 @@ - -from __future__ import unicode_literals -import frappe, erpnext -from frappe import _ -from frappe.utils import cint -from frappe.utils.nestedset import rebuild_tree - -def execute(): - """ - Patch Reference: - 1. check whether warehouse is associated to company or not - 2. if warehouse is associated with company - a. create warehouse group for company - b. set warehouse group as parent to other warehouses and set is_group as 0 - 3. if warehouses is not associated with company - a. get distinct companies from stock ledger entries - b. if sle have only company, - i. set default company to all warehouse - ii. repeat 2.a and 2.b - c. if have multiple companies, - i. create group warehouse without company - ii. repeat 2.b - """ - - frappe.reload_doc("stock", "doctype", "warehouse") - - if check_is_warehouse_associated_with_company(): - for company in frappe.get_all("Company", fields=["name", "abbr"]): - make_warehouse_nestedset(company) - else: - sle_against_companies = frappe.db.sql_list("""select distinct company from `tabStock Ledger Entry`""") - - if len(sle_against_companies) == 1: - company = frappe.get_cached_value('Company', sle_against_companies[0], - fieldname=["name", "abbr"], as_dict=1) - set_company_to_warehouse(company.name) - make_warehouse_nestedset(company) - - elif len(sle_against_companies) > 1: - make_warehouse_nestedset() - -def check_is_warehouse_associated_with_company(): - warehouse_associcated_with_company = False - - for warehouse in frappe.get_all("Warehouse", fields=["name", "company"]): - if warehouse.company: - warehouse_associcated_with_company = True - - return warehouse_associcated_with_company - -def make_warehouse_nestedset(company=None): - validate_parent_account_for_warehouse(company) - stock_account_group = get_stock_account_group(company.name) - enable_perpetual_inventory = cint(erpnext.is_perpetual_inventory_enabled(company.name)) or 0 - if not stock_account_group and enable_perpetual_inventory: - return - - if company: - warehouse_group = "{0} - {1}".format(_("All Warehouses"), company.abbr) - ignore_mandatory = False - else: - warehouse_group = _("All Warehouses") - ignore_mandatory = True - - if not frappe.db.get_value("Warehouse", warehouse_group): - create_default_warehouse_group(company, stock_account_group, ignore_mandatory) - - set_parent_to_warehouse(warehouse_group, company) - if enable_perpetual_inventory: - set_parent_to_warehouse_account(company) - -def validate_parent_account_for_warehouse(company=None): - if not company: - return - - if cint(erpnext.is_perpetual_inventory_enabled(company.name)): - parent_account = frappe.db.sql("""select name from tabAccount - where account_type='Stock' and company=%s and is_group=1 - and (warehouse is null or warehouse = '')""", company.name) - - if not parent_account: - current_parent_accounts_for_warehouse = frappe.db.sql("""select parent_account from tabAccount - where account_type='Warehouse' and (warehouse is not null or warehouse != '') """) - - if current_parent_accounts_for_warehouse: - frappe.db.set_value("Account", current_parent_accounts_for_warehouse[0][0], "account_type", "Stock") - -def create_default_warehouse_group(company=None, stock_account_group=None, ignore_mandatory=False): - wh = frappe.get_doc({ - "doctype": "Warehouse", - "warehouse_name": _("All Warehouses"), - "is_group": 1, - "company": company.name if company else "", - "parent_warehouse": "" - }) - - if ignore_mandatory: - wh.flags.ignore_mandatory = ignore_mandatory - - wh.insert(ignore_permissions=True) - -def set_parent_to_warehouse(warehouse_group, company=None): - frappe.db.sql(""" update tabWarehouse set parent_warehouse = %s, is_group = 0 - where (is_group = 0 or is_group is null or is_group = '') and ifnull(company, '') = %s - """,(warehouse_group, company.name if company else "")) - - rebuild_tree("Warehouse", "parent_warehouse") - -def set_parent_to_warehouse_account(company): - frappe.db.sql(""" update tabAccount set parent_account = %s - where is_group = 0 and account_type = "Warehouse" - and (warehouse is not null or warehouse != '') and company = %s - """,("{0} - {1}".format(_("All Warehouses"), company.abbr), company.name)) - - rebuild_tree("Account", "parent_account") - -def set_company_to_warehouse(company): - frappe.db.sql("update tabWahouse set company=%s", company) - -def get_stock_account_group(company): - stock_account_group = frappe.db.get_all('Account', filters = {'company': company, 'is_group': 1, - 'account_type': 'Stock', 'root_type': 'Asset'}, limit=1) - - if not stock_account_group: - stock_account_group = frappe.db.get_all('Account', filters = {'company': company, 'is_group': 1, - 'parent_account': '', 'root_type': 'Asset'}, limit=1) - - return stock_account_group[0].name if stock_account_group else None \ No newline at end of file diff --git a/erpnext/patches/v7_0/fix_duplicate_icons.py b/erpnext/patches/v7_0/fix_duplicate_icons.py deleted file mode 100644 index 9f442029b5a..00000000000 --- a/erpnext/patches/v7_0/fix_duplicate_icons.py +++ /dev/null @@ -1,27 +0,0 @@ -from __future__ import unicode_literals -import frappe - -from frappe.desk.doctype.desktop_icon.desktop_icon import (sync_desktop_icons, - get_desktop_icons, set_hidden) -from erpnext.patches.v7_0.migrate_schools_to_erpnext import reload_doctypes_for_schools_icons - -def execute(): - '''hide new style icons if old ones are set''' - frappe.reload_doc('desk', 'doctype', 'desktop_icon') - - reload_doctypes_for_schools_icons() - - sync_desktop_icons() - - for user in frappe.get_all('User', filters={'user_type': 'System User'}): - desktop_icons = get_desktop_icons(user.name) - icons_dict = {} - for d in desktop_icons: - if not d.hidden: - icons_dict[d.module_name] = d - - for key in (('Selling', 'Customer'), ('Stock', 'Item'), ('Buying', 'Supplier'), - ('HR', 'Employee'), ('CRM', 'Lead'), ('Support', 'Issue'), ('Projects', 'Project')): - if key[0] in icons_dict and key[1] in icons_dict: - set_hidden(key[1], user.name, 1) - diff --git a/erpnext/patches/v7_0/fix_nonwarehouse_ledger_gl_entries_for_transactions.py b/erpnext/patches/v7_0/fix_nonwarehouse_ledger_gl_entries_for_transactions.py deleted file mode 100644 index 2bc09714d8b..00000000000 --- a/erpnext/patches/v7_0/fix_nonwarehouse_ledger_gl_entries_for_transactions.py +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import print_function, unicode_literals -import frappe, erpnext - -def execute(): - frappe.reload_doctype("Account") - - warehouses = frappe.db.sql("""select name, company from tabAccount - where account_type = 'Stock' and is_group = 0 - and (warehouse is null or warehouse = '')""", as_dict=1) - warehouses = [d.name for d in warehouses if erpnext.is_perpetual_inventory_enabled(d.company)] - - if len(warehouses) > 0: - warehouses = set_warehouse_for_stock_account(warehouses) - if not warehouses: - return - - stock_vouchers = frappe.db.sql("""select distinct sle.voucher_type, sle.voucher_no - from `tabStock Ledger Entry` sle - where sle.warehouse in (%s) and creation > '2016-05-01' - and not exists(select name from `tabGL Entry` - where account=sle.warehouse and voucher_type=sle.voucher_type and voucher_no=sle.voucher_no) - order by sle.posting_date""" % - ', '.join(['%s']*len(warehouses)), tuple(warehouses)) - - rejected = [] - for voucher_type, voucher_no in stock_vouchers: - try: - frappe.db.sql("""delete from `tabGL Entry` - where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no)) - - voucher = frappe.get_doc(voucher_type, voucher_no) - voucher.make_gl_entries() - frappe.db.commit() - except Exception as e: - print(frappe.get_traceback()) - rejected.append([voucher_type, voucher_no]) - frappe.db.rollback() - - print(rejected) - -def set_warehouse_for_stock_account(warehouse_account): - for account in warehouse_account: - if frappe.db.exists('Warehouse', account): - frappe.db.set_value("Account", account, "warehouse", account) - else: - warehouse_account.remove(account) - - return warehouse_account diff --git a/erpnext/patches/v7_0/make_guardian.py b/erpnext/patches/v7_0/make_guardian.py deleted file mode 100644 index 519969b38d1..00000000000 --- a/erpnext/patches/v7_0/make_guardian.py +++ /dev/null @@ -1,37 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - if frappe.db.exists("DocType", "Student"): - student_table_cols = frappe.db.get_table_columns("Student") - if "father_name" in student_table_cols: - - # 'Schools' module changed to the 'Education' - # frappe.reload_doc("schools", "doctype", "student") - # frappe.reload_doc("schools", "doctype", "guardian") - # frappe.reload_doc("schools", "doctype", "guardian_interest") - - frappe.reload_doc("education", "doctype", "student") - frappe.reload_doc("education", "doctype", "guardian") - frappe.reload_doc("education", "doctype", "guardian_interest") - frappe.reload_doc("hr", "doctype", "interest") - - fields = ["name", "father_name", "mother_name"] - - if "father_email_id" in student_table_cols: - fields += ["father_email_id", "mother_email_id"] - - students = frappe.get_all("Student", fields) - for stud in students: - if stud.father_name: - make_guardian(stud.father_name, stud.name, stud.father_email_id) - if stud.mother_name: - make_guardian(stud.mother_name, stud.name, stud.mother_email_id) - -def make_guardian(name, student, email=None): - frappe.get_doc({ - 'doctype': 'Guardian', - 'guardian_name': name, - 'email': email, - 'student': student - }).insert() diff --git a/erpnext/patches/v7_0/make_is_group_fieldtype_as_check.py b/erpnext/patches/v7_0/make_is_group_fieldtype_as_check.py deleted file mode 100644 index ba82e869fa1..00000000000 --- a/erpnext/patches/v7_0/make_is_group_fieldtype_as_check.py +++ /dev/null @@ -1,18 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - for doctype in ["Sales Person", "Customer Group", "Item Group", "Territory"]: - - # convert to 1 or 0 - frappe.db.sql("update `tab{doctype}` set is_group = if(is_group='Yes',1,0) " - .format(doctype=doctype)) - - frappe.db.commit() - - # alter fields to int - - frappe.db.sql("alter table `tab{doctype}` change is_group is_group int(1) default '0'" - .format(doctype=doctype)) - - frappe.reload_doctype(doctype) diff --git a/erpnext/patches/v7_0/merge_account_type_stock_and_warehouse_to_stock.py b/erpnext/patches/v7_0/merge_account_type_stock_and_warehouse_to_stock.py deleted file mode 100644 index 02808a742f3..00000000000 --- a/erpnext/patches/v7_0/merge_account_type_stock_and_warehouse_to_stock.py +++ /dev/null @@ -1,10 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doc("accounts", "doctype", "account") - - frappe.db.sql(""" update tabAccount set account_type = "Stock" - where account_type = "Warehouse" """) - - frappe.db.commit() \ No newline at end of file diff --git a/erpnext/patches/v7_0/migrate_mode_of_payments_v6_to_v7.py b/erpnext/patches/v7_0/migrate_mode_of_payments_v6_to_v7.py deleted file mode 100644 index e0e3f7075a1..00000000000 --- a/erpnext/patches/v7_0/migrate_mode_of_payments_v6_to_v7.py +++ /dev/null @@ -1,38 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doc('accounts', 'doctype', 'sales_invoice_timesheet') - frappe.reload_doc('accounts', 'doctype', 'sales_invoice_payment') - frappe.reload_doc('accounts', 'doctype', 'mode_of_payment') - - count = 0 - for data in frappe.db.sql("""select name, mode_of_payment, cash_bank_account, paid_amount, company - from `tabSales Invoice` si - where si.is_pos = 1 and si.docstatus < 2 - and si.cash_bank_account is not null and si.cash_bank_account != '' - and not exists(select name from `tabSales Invoice Payment` where parent=si.name)""", as_dict=1): - - if not data.mode_of_payment and not frappe.db.exists("Mode of Payment", "Cash"): - mop = frappe.new_doc("Mode of Payment") - mop.mode_of_payment = "Cash" - mop.type = "Cash" - mop.save() - - si_doc = frappe.get_doc('Sales Invoice', data.name) - row = si_doc.append('payments', { - 'mode_of_payment': data.mode_of_payment or 'Cash', - 'account': data.cash_bank_account, - 'type': frappe.db.get_value('Mode of Payment', data.mode_of_payment, 'type') or 'Cash', - 'amount': data.paid_amount - }) - row.db_update() - - si_doc.set_paid_amount() - si_doc.db_set("paid_amount", si_doc.paid_amount, update_modified = False) - si_doc.db_set("base_paid_amount", si_doc.base_paid_amount, update_modified = False) - - count +=1 - - if count % 200 == 0: - frappe.db.commit() \ No newline at end of file diff --git a/erpnext/patches/v7_0/migrate_schools_to_erpnext.py b/erpnext/patches/v7_0/migrate_schools_to_erpnext.py deleted file mode 100644 index b72bc137b61..00000000000 --- a/erpnext/patches/v7_0/migrate_schools_to_erpnext.py +++ /dev/null @@ -1,30 +0,0 @@ -from __future__ import unicode_literals -import frappe, os -from frappe.installer import remove_from_installed_apps - -def execute(): - reload_doctypes_for_schools_icons() - - frappe.reload_doc('website', 'doctype', 'portal_settings') - frappe.reload_doc('website', 'doctype', 'portal_menu_item') - frappe.reload_doc('buying', 'doctype', 'request_for_quotation') - - if 'schools' in frappe.get_installed_apps(): - if not frappe.db.exists('Module Def', 'Schools') and frappe.db.exists('Module Def', 'Academics'): - - # 'Schools' module changed to the 'Education' - # frappe.rename_doc("Module Def", "Academics", "Schools") - - frappe.rename_doc("Module Def", "Academics", "Education") - - remove_from_installed_apps("schools") - -def reload_doctypes_for_schools_icons(): - # 'Schools' module changed to the 'Education' - # base_path = frappe.get_app_path('erpnext', 'schools', 'doctype') - - base_path = frappe.get_app_path('erpnext', 'education', 'doctype') - for doctype in os.listdir(base_path): - if os.path.exists(os.path.join(base_path, doctype, doctype + '.json')) \ - and doctype not in ("fee_component", "assessment", "assessment_result"): - frappe.reload_doc('education', 'doctype', doctype) \ No newline at end of file diff --git a/erpnext/patches/v7_0/move_timelogbatch_from_salesinvoiceitem_to_salesinvoicetimesheet.py b/erpnext/patches/v7_0/move_timelogbatch_from_salesinvoiceitem_to_salesinvoicetimesheet.py deleted file mode 100644 index 998c4b674bf..00000000000 --- a/erpnext/patches/v7_0/move_timelogbatch_from_salesinvoiceitem_to_salesinvoicetimesheet.py +++ /dev/null @@ -1,17 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doc('accounts', 'doctype', 'sales_invoice') - frappe.reload_doc('accounts', 'doctype', 'sales_invoice_payment') - for time_sheet in frappe.db.sql(""" select sales_invoice, name, total_billable_amount from `tabTimesheet` - where sales_invoice is not null and docstatus < 2""", as_dict=True): - if not frappe.db.exists('Sales Invoice', time_sheet.sales_invoice): - continue - si_doc = frappe.get_doc('Sales Invoice', time_sheet.sales_invoice) - ts = si_doc.append('timesheets',{}) - ts.time_sheet = time_sheet.name - ts.billing_amount = time_sheet.total_billable_amount - ts.db_update() - si_doc.calculate_billing_amount_from_timesheet() - si_doc.db_set("total_billing_amount", si_doc.total_billing_amount, update_modified = False) \ No newline at end of file diff --git a/erpnext/patches/v7_0/po_status_issue_for_pr_return.py b/erpnext/patches/v7_0/po_status_issue_for_pr_return.py deleted file mode 100644 index 910814fd227..00000000000 --- a/erpnext/patches/v7_0/po_status_issue_for_pr_return.py +++ /dev/null @@ -1,40 +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 - -def execute(): - parent_list = [] - count = 0 - - frappe.reload_doc('stock', 'doctype', 'purchase_receipt') - frappe.reload_doc('stock', 'doctype', 'purchase_receipt_item') - - for data in frappe.db.sql(""" - select - `tabPurchase Receipt Item`.purchase_order, `tabPurchase Receipt Item`.name, - `tabPurchase Receipt Item`.item_code, `tabPurchase Receipt Item`.idx, - `tabPurchase Receipt Item`.parent - from - `tabPurchase Receipt Item`, `tabPurchase Receipt` - where - `tabPurchase Receipt Item`.parent = `tabPurchase Receipt`.name and - `tabPurchase Receipt Item`.purchase_order_item is null and - `tabPurchase Receipt Item`.purchase_order is not null and - `tabPurchase Receipt`.is_return = 1""", as_dict=1): - name = frappe.db.get_value('Purchase Order Item', - {'item_code': data.item_code, 'parent': data.purchase_order, 'idx': data.idx}, 'name') - - if name: - frappe.db.set_value('Purchase Receipt Item', data.name, 'purchase_order_item', name, update_modified=False) - parent_list.append(data.parent) - - count +=1 - if count % 200 == 0: - frappe.db.commit() - - if len(parent_list) > 0: - for parent in set(parent_list): - doc = frappe.get_doc('Purchase Receipt', parent) - doc.update_qty(update_modified=False) \ No newline at end of file diff --git a/erpnext/patches/v7_0/re_route.py b/erpnext/patches/v7_0/re_route.py deleted file mode 100644 index 3cec6f39b2c..00000000000 --- a/erpnext/patches/v7_0/re_route.py +++ /dev/null @@ -1,5 +0,0 @@ -from __future__ import unicode_literals -from frappe.patches.v7_0.re_route import update_routes - -def execute(): - update_routes(['Item', 'Item Group', 'Sales Partner', 'Job Opening']) \ No newline at end of file diff --git a/erpnext/patches/v7_0/remove_administrator_role_in_doctypes.py b/erpnext/patches/v7_0/remove_administrator_role_in_doctypes.py deleted file mode 100644 index 8c87c4e3d3e..00000000000 --- a/erpnext/patches/v7_0/remove_administrator_role_in_doctypes.py +++ /dev/null @@ -1,9 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.db.sql("""delete from tabDocPerm where role="Administrator" and parent in - ("Payment Gateway", "Payment Gateway Account", "Payment Request", "Academic Term", "Academic Year", "Course", - "Course Schedule", "Examination", "Fee Category", "Fee Structure", "Fees", "Instructor", "Program", "Program Enrollment Tool", - "Room", "Scheduling Tool", "Student", "Student Applicant", "Student Attendance", "Student Group", "Student Group Creation Tool") - """) \ No newline at end of file diff --git a/erpnext/patches/v7_0/remove_doctypes_and_reports.py b/erpnext/patches/v7_0/remove_doctypes_and_reports.py deleted file mode 100644 index 2356e2f6ee4..00000000000 --- a/erpnext/patches/v7_0/remove_doctypes_and_reports.py +++ /dev/null @@ -1,27 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - if frappe.db.table_exists("Time Log"): - frappe.db.sql("""delete from `tabDocType` - where name in('Time Log Batch', 'Time Log Batch Detail', 'Time Log')""") - - frappe.db.sql("""delete from `tabDocField` where parent in ('Time Log', 'Time Log Batch')""") - frappe.db.sql("""update `tabClient Script` set dt = 'Timesheet' where dt = 'Time Log'""") - - for data in frappe.db.sql(""" select label, fieldname from `tabCustom Field` where dt = 'Time Log'""", as_dict=1): - custom_field = frappe.get_doc({ - 'doctype': 'Custom Field', - 'label': data.label, - 'dt': 'Timesheet Detail', - 'fieldname': data.fieldname, - 'fieldtype': data.fieldtype or "Data" - }).insert(ignore_permissions=True) - - frappe.db.sql("""delete from `tabCustom Field` where dt = 'Time Log'""") - frappe.reload_doc('projects', 'doctype', 'timesheet') - frappe.reload_doc('projects', 'doctype', 'timesheet_detail') - - report = "Daily Time Log Summary" - if frappe.db.exists("Report", report): - frappe.delete_doc('Report', report) diff --git a/erpnext/patches/v7_0/remove_features_setup.py b/erpnext/patches/v7_0/remove_features_setup.py deleted file mode 100644 index 49393cc248d..00000000000 --- a/erpnext/patches/v7_0/remove_features_setup.py +++ /dev/null @@ -1,29 +0,0 @@ -from __future__ import unicode_literals -import frappe - -from erpnext.setup.install import create_compact_item_print_custom_field -from frappe.utils import cint - -def execute(): - frappe.reload_doctype('Stock Settings') - stock_settings = frappe.get_doc('Stock Settings', 'Stock Settings') - stock_settings.show_barcode_field = cint(frappe.db.get_value("Features Setup", None, "fs_item_barcode")) - if not frappe.db.exists("UOM", stock_settings.stock_uom): - stock_settings.stock_uom = None - stock_settings.save() - - create_compact_item_print_custom_field() - - compact_item_print = frappe.db.get_value("Features Setup", None, "compact_item_print") - frappe.db.set_value("Print Settings", None, "compact_item_print", compact_item_print) - - # remove defaults - frappe.db.sql("""delete from tabDefaultValue where defkey in ('fs_item_serial_nos', - 'fs_item_batch_nos', 'fs_brands', 'fs_item_barcode', - 'fs_item_advanced', 'fs_packing_details', 'fs_item_group_in_details', - 'fs_exports', 'fs_imports', 'fs_discounts', 'fs_purchase_discounts', - 'fs_after_sales_installations', 'fs_projects', 'fs_sales_extras', - 'fs_recurring_invoice', 'fs_pos', 'fs_manufacturing', 'fs_quality', - 'fs_page_break', 'fs_more_info', 'fs_pos_view', 'compact_item_print')""") - - frappe.delete_doc('DocType', 'Features Setup') diff --git a/erpnext/patches/v7_0/remove_old_earning_deduction_doctypes.py b/erpnext/patches/v7_0/remove_old_earning_deduction_doctypes.py deleted file mode 100644 index 05a2c49461c..00000000000 --- a/erpnext/patches/v7_0/remove_old_earning_deduction_doctypes.py +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - if frappe.db.exists("DocType", "Salary Component"): - for dt in ("Salary Structure Earning", "Salary Structure Deduction", "Salary Slip Earning", - "Salary Slip Deduction", "Earning Type", "Deduction Type"): - frappe.delete_doc("DocType", dt) - - - for d in frappe.db.sql("""select name from `tabCustom Field` - where dt in ('Salary Detail', 'Salary Component')"""): - frappe.get_doc("Custom Field", d[0]).save() \ No newline at end of file diff --git a/erpnext/patches/v7_0/rename_advance_table_fields.py b/erpnext/patches/v7_0/rename_advance_table_fields.py deleted file mode 100644 index 34d81343e2b..00000000000 --- a/erpnext/patches/v7_0/rename_advance_table_fields.py +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe -from frappe.model.utils.rename_field import rename_field - -def execute(): - for dt in ("Sales Invoice Advance", "Purchase Invoice Advance"): - frappe.reload_doctype(dt) - - frappe.db.sql("update `tab{0}` set reference_type = 'Journal Entry'".format(dt)) - - if frappe.get_meta(dt).has_field('journal_entry'): - rename_field(dt, "journal_entry", "reference_name") - - if frappe.get_meta(dt).has_field('jv_detail_no'): - rename_field(dt, "jv_detail_no", "reference_row") \ No newline at end of file diff --git a/erpnext/patches/v7_0/rename_examination_to_assessment.py b/erpnext/patches/v7_0/rename_examination_to_assessment.py deleted file mode 100644 index dc248de4fae..00000000000 --- a/erpnext/patches/v7_0/rename_examination_to_assessment.py +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -from frappe.model.utils.rename_field import rename_field - -def execute(): - if frappe.db.exists("DocType", "Examination"): - frappe.rename_doc("DocType", "Examination", "Assessment") - frappe.rename_doc("DocType", "Examination Result", "Assessment Result") - - # 'Schools' module changed to the 'Education' - # frappe.reload_doc("schools", "doctype", "assessment") - # frappe.reload_doc("schools", "doctype", "assessment_result") - - frappe.reload_doc("education", "doctype", "assessment") - frappe.reload_doc("education", "doctype", "assessment_result") - - rename_field("Assessment", "exam_name", "assessment_name") - rename_field("Assessment", "exam_code", "assessment_code") - - frappe.db.sql("delete from `tabPortal Menu Item` where route = '/examination'") \ No newline at end of file diff --git a/erpnext/patches/v7_0/rename_fee_amount_to_fee_component.py b/erpnext/patches/v7_0/rename_fee_amount_to_fee_component.py deleted file mode 100644 index 5cb6a3b7c43..00000000000 --- a/erpnext/patches/v7_0/rename_fee_amount_to_fee_component.py +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -from frappe.model.utils.rename_field import rename_field - -def execute(): - if frappe.db.exists("DocType", "Fee Amount"): - frappe.rename_doc("DocType", "Fee Amount", "Fee Component") - for dt in ("Fees", "Fee Structure"): - frappe.reload_doctype(dt) - rename_field(dt, "amount", "components") - - \ No newline at end of file diff --git a/erpnext/patches/v7_0/rename_prevdoc_fields.py b/erpnext/patches/v7_0/rename_prevdoc_fields.py deleted file mode 100644 index ded4ad4aaee..00000000000 --- a/erpnext/patches/v7_0/rename_prevdoc_fields.py +++ /dev/null @@ -1,76 +0,0 @@ -from __future__ import unicode_literals -import frappe -import json -from frappe.model.utils.rename_field import update_reports, rename_field, update_property_setters -from frappe.custom.doctype.property_setter.property_setter import make_property_setter - -def execute(): - frappe.reload_doctype('Purchase Order Item') - frappe.reload_doctype('Purchase Receipt Item') - update_po_fields() - update_prop_setters_reports_print_format_for_po() - set_sales_order_field() - rename_pr_fields() - -def update_po_fields(): - for data in frappe.db.sql(""" select prevdoc_docname, prevdoc_detail_docname, name, prevdoc_doctype - from `tabPurchase Order Item` where prevdoc_doctype is not null""", as_dict=True): - if data.prevdoc_doctype == 'Material Request': - frappe.db.set_value("Purchase Order Item", data.name, "material_request", data.prevdoc_docname, update_modified=False) - frappe.db.set_value("Purchase Order Item", data.name, "material_request_item", data.prevdoc_detail_docname, update_modified=False) - elif data.prevdoc_doctype == 'Sales Order': - frappe.db.set_value("Purchase Order Item", data.name, "sales_order", data.prevdoc_docname, update_modified=False) - frappe.db.set_value("Purchase Order Item", data.name, "sales_order_item", data.prevdoc_detail_docname, update_modified=False) - -def get_columns(): - return { - 'prevdoc_docname': 'material_request', - 'prevdoc_detail_docname': 'material_request_item' - } - -def update_prop_setters_reports_print_format_for_po(): - for key, val in get_columns().items(): - update_property_setters('Purchase Order Item', key, val) - update_reports('Purchase Order Item', key, val) - update_print_format_for_po(key, val, 'Purchase Order') - -def update_print_format_for_po(old_fieldname, new_fieldname, doc_type): - column_mapper = get_columns() - - for data in frappe.db.sql(""" select name, format_data from `tabPrint Format` where - format_data like %(old_fieldname)s and doc_type = %(doc_type)s""", - {'old_fieldname': '%%%s%%'%(old_fieldname), 'doc_type': doc_type}, as_dict=True): - - update_print_format_fields(old_fieldname, new_fieldname, data) - -def update_print_format_fields(old_fieldname, new_fieldname, args): - report_dict = json.loads(args.format_data) - update = False - - for col in report_dict: - if col.get('fieldname') and col.get('fieldname') == old_fieldname: - col['fieldname'] = new_fieldname - update = True - - if col.get('visible_columns'): - for key in col.get('visible_columns'): - if key.get('fieldname') == old_fieldname: - key['fieldname'] = new_fieldname - update = True - - if update: - val = json.dumps(report_dict) - frappe.db.sql("""update `tabPrint Format` set `format_data`=%s where name=%s""", (val, args.name)) - -def set_sales_order_field(): - for data in frappe.db.sql("""select doc_type, field_name, property, value, property_type - from `tabProperty Setter` where doc_type = 'Purchase Order Item' - and field_name in('material_request', 'material_request_item')""", as_dict=True): - if data.field_name == 'material_request': - make_property_setter(data.doc_type, 'sales_order', data.property, data.value, data.property_type) - else: - make_property_setter(data.doc_type, 'sales_order_item', data.property, data.value, data.property_type) - -def rename_pr_fields(): - rename_field("Purchase Receipt Item", "prevdoc_docname", "purchase_order") - rename_field("Purchase Receipt Item", "prevdoc_detail_docname", "purchase_order_item") diff --git a/erpnext/patches/v7_0/rename_salary_components.py b/erpnext/patches/v7_0/rename_salary_components.py deleted file mode 100644 index 1693f3bdf1f..00000000000 --- a/erpnext/patches/v7_0/rename_salary_components.py +++ /dev/null @@ -1,149 +0,0 @@ -from __future__ import unicode_literals -import frappe -from frappe.model.utils.rename_field import update_property_setters - -def execute(): - if not frappe.db.exists("DocType", "Salary Structure Earning"): - return - - frappe.reload_doc("Payroll", "doctype", "salary_detail") - frappe.reload_doc("Payroll", "doctype", "salary_component") - - standard_cols = ["name", "creation", "modified", "owner", "modified_by", "parent", "parenttype", "parentfield", "idx"] - - dt_cols = { - "Salary Structure Deduction": ["d_type", "d_modified_amt", "depend_on_lwp"], - "Salary Structure Earning": ["e_type", "modified_value", "depend_on_lwp"], - "Salary Slip Earning": ["e_type", "e_modified_amount", "e_depends_on_lwp", "e_amount"], - "Salary Slip Deduction": ["d_type", "d_modified_amount", "d_depends_on_lwp", "d_amount"], - } - - earning_type_exists = True if "earning_type" in frappe.db.get_table_columns("Salary Slip Earning") else False - e_type_exists = True if "e_type" in frappe.db.get_table_columns("Salary Slip Earning") else False - - - if e_type_exists and earning_type_exists: - frappe.db.sql("""update `tabSalary Slip Earning` - set e_type = earning_type, e_modified_amount = earning_amount - where e_type is null and earning_type is not null""") - - frappe.db.sql("""update `tabSalary Structure Earning` set e_type = earning_type - where e_type is null and earning_type is not null""") - - frappe.db.sql("""update `tabSalary Slip Deduction` set - d_type = deduction_type, d_modified_amount = deduction_amount - where d_type is null and deduction_type is not null""") - - frappe.db.sql("""update `tabSalary Structure Deduction` set d_type = deduction_type - where d_type is null and deduction_type is not null""") - - if earning_type_exists and not e_type_exists: - for val in dt_cols.values(): - if val[0] == "e_type": - val[0] = "earning_type" - - if val[0] == "d_type": - val[0] = "deduction_type" - - if val[1] == "e_modified_amount": - val[1] ="earning_amount" - - if val[1] == "d_modified_amount": - val[1] ="deduction_amount" - - - - target_cols = standard_cols + ["salary_component", "amount", "depends_on_payment_days", "default_amount"] - target_cols = "`" + "`, `".join(target_cols) + "`" - - for doctype, cols in dt_cols.items(): - source_cols = "`" + "`, `".join(standard_cols + cols) + "`" - if len(cols) == 3: - source_cols += ", 0" - - - frappe.db.sql("""INSERT INTO `tabSalary Detail` ({0}) SELECT {1} FROM `tab{2}`""" - .format(target_cols, source_cols, doctype)) - - - dt_cols_de = { - "Deduction Type": ["deduction_name", "description"], - "Earning Type": ["earning_name", "description"], - } - - standard_cols_de = standard_cols - - - target_cols = standard_cols_de + ["salary_component", "description"] - target_cols = "`" + "`, `".join(target_cols) + "`" - - for doctype, cols in dt_cols_de.items(): - source_cols = "`" + "`, `".join(standard_cols_de + cols) + "`" - try: - frappe.db.sql("""INSERT INTO `tabSalary Component` ({0}) SELECT {1} FROM `tab{2}`""" - .format(target_cols, source_cols, doctype)) - except Exception as e: - if e.args[0]==1062: - pass - - update_customizations() - - for doctype in ["Salary Structure Deduction", "Salary Structure Earning", "Salary Slip Earning", - "Salary Slip Deduction", "Deduction Type", "Earning Type"] : - frappe.delete_doc("DocType", doctype) - - -def update_customizations(): - dt_cols = { - "Salary Structure Deduction": { - "d_type": "salary_component", - "deduction_type": "salary_component", - "d_modified_amt": "amount", - "depend_on_lwp": "depends_on_payment_days" - }, - "Salary Structure Earning": { - "e_type": "salary_component", - "earning_type": "salary_component", - "modified_value": "amount", - "depend_on_lwp": "depends_on_payment_days" - }, - "Salary Slip Earning": { - "e_type": "salary_component", - "earning_type": "salary_component", - "e_modified_amount": "amount", - "e_amount" : "default_amount", - "e_depends_on_lwp": "depends_on_payment_days" - }, - "Salary Slip Deduction": { - "d_type": "salary_component", - "deduction_type": "salary_component", - "d_modified_amount": "amount", - "d_amount" : "default_amount", - "d_depends_on_lwp": "depends_on_payment_days" - } - } - - update_property_setters_and_custom_fields("Salary Detail", dt_cols) - - dt_cols = { - "Earning Type": { - "earning_name": "salary_component" - }, - "Deduction Type": { - "deduction_name": "salary_component" - } - } - - update_property_setters_and_custom_fields("Salary Component", dt_cols) - - - - -def update_property_setters_and_custom_fields(new_dt, dt_cols): - for doctype, cols in dt_cols.items(): - frappe.db.sql("update `tabProperty Setter` set doc_type = %s where doc_type=%s", (new_dt, doctype)) - frappe.db.sql("update `tabCustom Field` set dt = %s where dt=%s", (new_dt, doctype)) - - - for old_fieldname, new_fieldname in cols.items(): - update_property_setters(new_dt, old_fieldname, new_fieldname) diff --git a/erpnext/patches/v7_0/rename_time_sheet_doctype.py b/erpnext/patches/v7_0/rename_time_sheet_doctype.py deleted file mode 100644 index f80a8301d78..00000000000 --- a/erpnext/patches/v7_0/rename_time_sheet_doctype.py +++ /dev/null @@ -1,14 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - if frappe.db.table_exists("Time Sheet") and not frappe.db.table_exists("Timesheet"): - frappe.rename_doc("DocType", "Time Sheet", "Timesheet") - frappe.rename_doc("DocType", "Time Sheet Detail", "Timesheet Detail") - - for doctype in ['Time Sheet', 'Time Sheet Detail']: - frappe.delete_doc('DocType', doctype) - - report = "Daily Time Sheet Summary" - if frappe.db.exists("Report", report): - frappe.delete_doc('Report', report) diff --git a/erpnext/patches/v7_0/repost_bin_qty_and_item_projected_qty.py b/erpnext/patches/v7_0/repost_bin_qty_and_item_projected_qty.py deleted file mode 100644 index a5cf22cf015..00000000000 --- a/erpnext/patches/v7_0/repost_bin_qty_and_item_projected_qty.py +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - repost_bin_qty() - -def repost_bin_qty(): - for bin in frappe.db.sql(""" select name from `tabBin` - where (actual_qty + ordered_qty + indented_qty + planned_qty - reserved_qty - reserved_qty_for_production - reserved_qty_for_sub_contract) != projected_qty """, as_dict=1): - bin_doc = frappe.get_doc('Bin', bin.name) - bin_doc.set_projected_qty() - bin_doc.db_set("projected_qty", bin_doc.projected_qty, update_modified = False) diff --git a/erpnext/patches/v7_0/repost_gle_for_pi_with_update_stock.py b/erpnext/patches/v7_0/repost_gle_for_pi_with_update_stock.py deleted file mode 100644 index b864e597b82..00000000000 --- a/erpnext/patches/v7_0/repost_gle_for_pi_with_update_stock.py +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe -from frappe.utils import cint - -def execute(): - frappe.reload_doctype("Purchase Invoice") - - for pi in frappe.db.sql("""select name from `tabPurchase Invoice` - where company in(select name from tabCompany where enable_perpetual_inventory = 1) and - update_stock=1 and docstatus=1 order by posting_date asc""", as_dict=1): - - frappe.db.sql("""delete from `tabGL Entry` - where voucher_type = 'Purchase Invoice' and voucher_no = %s""", pi.name) - - pi_doc = frappe.get_doc("Purchase Invoice", pi.name) - pi_doc.make_gl_entries() - frappe.db.commit() \ No newline at end of file diff --git a/erpnext/patches/v7_0/repost_gle_for_pos_sales_return.py b/erpnext/patches/v7_0/repost_gle_for_pos_sales_return.py deleted file mode 100644 index 77ecafd6f14..00000000000 --- a/erpnext/patches/v7_0/repost_gle_for_pos_sales_return.py +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe -from frappe.utils import cint, flt - -def execute(): - frappe.reload_doctype("Sales Invoice") - frappe.reload_doctype("Sales Invoice Item") - - for si in frappe.get_all("Sales Invoice", fields = ["name"], - filters={"docstatus": 1, "is_pos": 1, "is_return": 1}): - si_doc = frappe.get_doc("Sales Invoice", si.name) - if len(si_doc.payments) > 0: - si_doc.set_paid_amount() - si_doc.flags.ignore_validate_update_after_submit = True - si_doc.save() - if si_doc.grand_total <= si_doc.paid_amount and si_doc.paid_amount < 0: - delete_gle_for_voucher(si_doc.name) - si_doc.run_method("make_gl_entries") - -def delete_gle_for_voucher(voucher_no): - frappe.db.sql("""delete from `tabGL Entry` where voucher_no = %(voucher_no)s""", - {'voucher_no': voucher_no}) diff --git a/erpnext/patches/v7_0/set_base_amount_in_invoice_payment_table.py b/erpnext/patches/v7_0/set_base_amount_in_invoice_payment_table.py deleted file mode 100644 index 5dd61a06cce..00000000000 --- a/erpnext/patches/v7_0/set_base_amount_in_invoice_payment_table.py +++ /dev/null @@ -1,24 +0,0 @@ -from __future__ import unicode_literals -import frappe -from frappe.utils import flt - -def execute(): - si_list = frappe.db.sql(""" - select distinct parent - from `tabSales Invoice Payment` - where docstatus!=2 and parenttype = 'Sales Invoice' - and amount != 0 and base_amount = 0 - """) - - count = 0 - for d in si_list: - si = frappe.get_doc("Sales Invoice", d[0]) - for p in si.get("payments"): - if p.amount and not p.base_amount: - base_amount = flt(p.amount*si.conversion_rate, si.precision("base_paid_amount")) - frappe.db.set_value("Sales Invoice Payment", p.name, "base_amount", base_amount, update_modified=False) - - count +=1 - - if count % 200 == 0: - frappe.db.commit() diff --git a/erpnext/patches/v7_0/set_is_group_for_warehouse.py b/erpnext/patches/v7_0/set_is_group_for_warehouse.py deleted file mode 100644 index 3e69616b803..00000000000 --- a/erpnext/patches/v7_0/set_is_group_for_warehouse.py +++ /dev/null @@ -1,7 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doc("stock", "doctype", "warehouse") - frappe.db.sql("""update tabWarehouse - set is_group = if ((ifnull(is_group, "No") = "Yes" or ifnull(is_group, 0) = 1), 1, 0)""") \ No newline at end of file diff --git a/erpnext/patches/v7_0/set_material_request_type_in_item.py b/erpnext/patches/v7_0/set_material_request_type_in_item.py deleted file mode 100644 index 5fb14adbc8d..00000000000 --- a/erpnext/patches/v7_0/set_material_request_type_in_item.py +++ /dev/null @@ -1,16 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doctype("Item") - if "default_bom" in frappe.db.get_table_columns("Item"): - frappe.db.sql("""update `tabItem` - set default_material_request_type = ( - case - when (default_bom is not null and default_bom != '') - then 'Manufacture' - else 'Purchase' - end )""") - - else: - frappe.db.sql("update tabItem set default_material_request_type='Purchase'") \ No newline at end of file diff --git a/erpnext/patches/v7_0/set_naming_series_for_timesheet.py b/erpnext/patches/v7_0/set_naming_series_for_timesheet.py deleted file mode 100644 index d4d1a69d215..00000000000 --- a/erpnext/patches/v7_0/set_naming_series_for_timesheet.py +++ /dev/null @@ -1,15 +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.custom.doctype.property_setter.property_setter import make_property_setter - -def execute(): - frappe.reload_doc('projects', 'doctype', 'timesheet') - frappe.reload_doc('projects', 'doctype', 'timesheet_detail') - frappe.reload_doc('accounts', 'doctype', 'sales_invoice_timesheet') - - make_property_setter('Timesheet', "naming_series", "options", 'TS-', "Text") - make_property_setter('Timesheet', "naming_series", "default", 'TS-', "Text") \ No newline at end of file diff --git a/erpnext/patches/v7_0/set_party_name_in_payment_entry.py b/erpnext/patches/v7_0/set_party_name_in_payment_entry.py deleted file mode 100644 index bbdcf5cf3ca..00000000000 --- a/erpnext/patches/v7_0/set_party_name_in_payment_entry.py +++ /dev/null @@ -1,20 +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 - -def execute(): - customers = frappe._dict(frappe.db.sql("select name, customer_name from tabCustomer")) - suppliers = frappe._dict(frappe.db.sql("select name, supplier_name from tabSupplier")) - - frappe.reload_doc('accounts', 'doctype', 'payment_entry') - - pe_list = frappe.db.sql("""select name, party_type, party from `tabPayment Entry` - where party is not null and party != ''""", as_dict=1) - for pe in pe_list: - party_name = customers.get(pe.party) if pe.party_type=="Customer" else suppliers.get(pe.party) - - frappe.db.set_value("Payment Entry", pe.name, "party_name", party_name, update_modified=False) - diff --git a/erpnext/patches/v7_0/set_portal_settings.py b/erpnext/patches/v7_0/set_portal_settings.py deleted file mode 100644 index 5259d4fbd44..00000000000 --- a/erpnext/patches/v7_0/set_portal_settings.py +++ /dev/null @@ -1,28 +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 - -def execute(): - frappe.reload_doctype('Role') - for dt in ("assessment", "course", "fees"): - # 'Schools' module changed to the 'Education' - # frappe.reload_doc("schools", "doctype", dt) - frappe.reload_doc("education", "doctype", dt) - - for dt in ("domain", "has_domain", "domain_settings"): - frappe.reload_doc("core", "doctype", dt) - - frappe.reload_doc('website', 'doctype', 'portal_menu_item') - - frappe.get_doc('Portal Settings').sync_menu() - - if 'schools' in frappe.get_installed_apps(): - domain = frappe.get_doc('Domain', 'Education') - domain.setup_domain() - else: - domain = frappe.get_doc('Domain', 'Manufacturing') - domain.setup_data() - domain.setup_sidebar_items() diff --git a/erpnext/patches/v7_0/setup_account_table_for_expense_claim_type_if_exists.py b/erpnext/patches/v7_0/setup_account_table_for_expense_claim_type_if_exists.py deleted file mode 100644 index c5657079b33..00000000000 --- a/erpnext/patches/v7_0/setup_account_table_for_expense_claim_type_if_exists.py +++ /dev/null @@ -1,20 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doc("hr", "doctype", "expense_claim_type") - frappe.reload_doc("hr", "doctype", "expense_claim_account") - - if not frappe.db.has_column('Expense Claim Type', 'default_account'): - return - - for expense_claim_type in frappe.get_all("Expense Claim Type", fields=["name", "default_account"]): - if expense_claim_type.default_account \ - and frappe.db.exists("Account", expense_claim_type.default_account): - doc = frappe.get_doc("Expense Claim Type", expense_claim_type.name) - doc.append("accounts", { - "company": frappe.db.get_value("Account", expense_claim_type.default_account, "company"), - "default_account": expense_claim_type.default_account, - }) - doc.flags.ignore_mandatory = True - doc.save(ignore_permissions=True) \ No newline at end of file diff --git a/erpnext/patches/v7_0/system_settings_setup_complete.py b/erpnext/patches/v7_0/system_settings_setup_complete.py deleted file mode 100644 index 0feeee981e6..00000000000 --- a/erpnext/patches/v7_0/system_settings_setup_complete.py +++ /dev/null @@ -1,16 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doctype('System Settings') - companies = frappe.db.sql("""select name, country - from tabCompany order by creation asc""", as_dict=True) - if companies: - frappe.db.set_value('System Settings', 'System Settings', 'setup_complete', 1) - - for company in companies: - if company.country: - frappe.db.set_value('System Settings', 'System Settings', 'country', company.country) - break - - diff --git a/erpnext/patches/v7_0/update_autoname_field.py b/erpnext/patches/v7_0/update_autoname_field.py deleted file mode 100644 index bfa9b281df3..00000000000 --- a/erpnext/patches/v7_0/update_autoname_field.py +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - doctypes = frappe.db.sql(""" select name, autoname from `tabDocType` - where autoname like 'field:%' and allow_rename = 1""", as_dict=1) - - for doctype in doctypes: - fieldname = doctype.autoname.split(":")[1] - if fieldname: - frappe.db.sql(""" update `tab%s` set %s = name """%(doctype.name, fieldname)) \ No newline at end of file diff --git a/erpnext/patches/v7_0/update_change_amount_account.py b/erpnext/patches/v7_0/update_change_amount_account.py deleted file mode 100644 index 1741095ea96..00000000000 --- a/erpnext/patches/v7_0/update_change_amount_account.py +++ /dev/null @@ -1,19 +0,0 @@ -from __future__ import unicode_literals -import frappe -from erpnext.accounts.doctype.journal_entry.journal_entry import get_default_bank_cash_account - -def execute(): - frappe.reload_doc('accounts', 'doctype', 'sales_invoice') - - for company in frappe.db.sql("""select company from `tabSales Invoice` - where change_amount <> 0 and account_for_change_amount is null group by company""", as_list = 1): - cash_account = get_default_bank_cash_account(company[0], 'Cash').get('account') - if not cash_account: - bank_account = get_default_bank_cash_account(company[0], 'Bank').get('account') - cash_account = bank_account - - if cash_account: - frappe.db.sql("""update `tabSales Invoice` - set account_for_change_amount = %(cash_account)s where change_amount <> 0 - and company = %(company)s and account_for_change_amount is null""", - {'cash_account': cash_account, 'company': company[0]}) diff --git a/erpnext/patches/v7_0/update_conversion_factor_in_supplier_quotation_item.py b/erpnext/patches/v7_0/update_conversion_factor_in_supplier_quotation_item.py deleted file mode 100644 index 24da4b1aebf..00000000000 --- a/erpnext/patches/v7_0/update_conversion_factor_in_supplier_quotation_item.py +++ /dev/null @@ -1,19 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doc('buying', 'doctype', 'supplier_quotation_item') - - frappe.db.sql("""update - `tabSupplier Quotation Item` as sqi_t, - (select sqi.item_code as item_code, sqi.uom as uom, ucd.conversion_factor as conversion_factor - from `tabSupplier Quotation Item` sqi left join `tabUOM Conversion Detail` ucd - on ucd.uom = sqi.uom and sqi.item_code = ucd.parent) as conversion_data, - `tabItem` as item - set - sqi_t.conversion_factor= ifnull(conversion_data.conversion_factor, 1), - sqi_t.stock_qty = (ifnull(conversion_data.conversion_factor, 1) * sqi_t.qty), - sqi_t.stock_uom = item.stock_uom - where - sqi_t.item_code = conversion_data.item_code and - sqi_t.uom = conversion_data.uom and sqi_t.item_code = item.name""") \ No newline at end of file diff --git a/erpnext/patches/v7_0/update_home_page.py b/erpnext/patches/v7_0/update_home_page.py deleted file mode 100644 index 909825c5721..00000000000 --- a/erpnext/patches/v7_0/update_home_page.py +++ /dev/null @@ -1,27 +0,0 @@ -from __future__ import unicode_literals -import frappe -import erpnext - -def execute(): - frappe.reload_doc('portal', 'doctype', 'homepage_featured_product') - frappe.reload_doc('portal', 'doctype', 'homepage') - frappe.reload_doc('portal', 'doctype', 'products_settings') - frappe.reload_doctype('Item') - frappe.reload_doctype('Item Group') - - website_settings = frappe.get_doc('Website Settings', 'Website Settings') - if frappe.db.exists('Web Page', website_settings.home_page): - header = frappe.db.get_value('Web Page', website_settings.home_page, 'header') - if header and header.startswith("
    "): - homepage = frappe.get_doc('Homepage', 'Homepage') - homepage.company = erpnext.get_default_company() or frappe.get_all("Company")[0].name - if '

    ' in header: - homepage.tag_line = header.split('

    ')[1].split('

    ')[0] or 'Default Website' - else: - homepage.tag_line = 'Default Website' - homepage.setup_items() - homepage.save() - - website_settings.home_page = 'home' - website_settings.save() - diff --git a/erpnext/patches/v7_0/update_maintenance_module_in_doctype.py b/erpnext/patches/v7_0/update_maintenance_module_in_doctype.py deleted file mode 100644 index 4c0c6a9313e..00000000000 --- a/erpnext/patches/v7_0/update_maintenance_module_in_doctype.py +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors - -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.db.set_value("DocType", "Maintenance Schedule", "module", "Maintenance") - frappe.db.set_value("DocType", "Maintenance Schedule Detail", "module", "Maintenance") - frappe.db.set_value("DocType", "Maintenance Schedule Item", "module", "Maintenance") - frappe.db.set_value("DocType", "Maintenance Visit", "module", "Maintenance") - frappe.db.set_value("DocType", "Maintenance Visit Purpose", "module", "Maintenance") \ No newline at end of file diff --git a/erpnext/patches/v7_0/update_mins_to_first_response.py b/erpnext/patches/v7_0/update_mins_to_first_response.py deleted file mode 100644 index 16681357e68..00000000000 --- a/erpnext/patches/v7_0/update_mins_to_first_response.py +++ /dev/null @@ -1,24 +0,0 @@ -from __future__ import unicode_literals -import frappe - -from frappe.core.doctype.communication.communication import update_mins_to_first_communication - -def execute(): - frappe.reload_doctype('Issue') - frappe.reload_doctype('Opportunity') - - for doctype in ('Issue', 'Opportunity'): - frappe.db.sql('update tab{0} set mins_to_first_response=0'.format(doctype)) - for parent in frappe.get_all(doctype, order_by='creation desc', limit=500): - parent_doc = frappe.get_doc(doctype, parent.name) - for communication in frappe.get_all('Communication', - filters={'reference_doctype': doctype, 'reference_name': parent.name, - 'communication_medium': 'Email'}, - order_by = 'creation asc', limit=2): - - communication_doc = frappe.get_doc('Communication', communication.name) - - update_mins_to_first_communication(parent_doc, communication_doc) - - if parent_doc.mins_to_first_response: - continue \ No newline at end of file diff --git a/erpnext/patches/v7_0/update_missing_employee_in_timesheet.py b/erpnext/patches/v7_0/update_missing_employee_in_timesheet.py deleted file mode 100644 index 54d492b2658..00000000000 --- a/erpnext/patches/v7_0/update_missing_employee_in_timesheet.py +++ /dev/null @@ -1,20 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - if frappe.db.table_exists("Time Log") and "employee" in frappe.db.get_table_columns("Time Log"): - timesheet = frappe.db.sql("""select tl.employee as employee, ts.name as name, - tl.modified as modified, tl.modified_by as modified_by, tl.creation as creation, tl.owner as owner - from - `tabTimesheet` ts, `tabTimesheet Detail` tsd, `tabTime Log` tl - where - tsd.parent = ts.name and tl.from_time = tsd.from_time and tl.to_time = tsd.to_time - and tl.hours = tsd.hours and tl.billing_rate = tsd.billing_rate and tsd.idx=1 - and tl.docstatus < 2 and (ts.employee = '' or ts.employee is null)""", as_dict=1) - - for data in timesheet: - ts_doc = frappe.get_doc('Timesheet', data.name) - if len(ts_doc.time_logs) == 1: - frappe.db.sql(""" update `tabTimesheet` set creation = %(creation)s, - owner = %(owner)s, modified = %(modified)s, modified_by = %(modified_by)s, - employee = %(employee)s where name = %(name)s""", data) diff --git a/erpnext/patches/v7_0/update_mode_of_payment_type.py b/erpnext/patches/v7_0/update_mode_of_payment_type.py deleted file mode 100644 index 9292a1be1b9..00000000000 --- a/erpnext/patches/v7_0/update_mode_of_payment_type.py +++ /dev/null @@ -1,29 +0,0 @@ -from __future__ import unicode_literals -import frappe -from frappe.utils import flt - -def execute(): - frappe.reload_doc('accounts', 'doctype', 'mode_of_payment') - - frappe.db.sql(""" update `tabMode of Payment` set type = 'Cash' where (type is null or type = '') and name = 'Cash'""") - - for data in frappe.db.sql("""select name from `tabSales Invoice` where is_pos=1 and docstatus<2 and - (ifnull(paid_amount, 0) - ifnull(change_amount, 0)) > ifnull(grand_total, 0) and modified > '2016-05-01'""", as_dict=1): - if data.name: - si_doc = frappe.get_doc("Sales Invoice", data.name) - remove_payment = [] - mode_of_payment = [d.mode_of_payment for d in si_doc.payments if flt(d.amount) > 0] - if mode_of_payment != set(mode_of_payment): - for payment_data in si_doc.payments: - if payment_data.idx != 1 and payment_data.amount == si_doc.grand_total: - remove_payment.append(payment_data) - frappe.db.sql(""" delete from `tabSales Invoice Payment` - where name = %(name)s""", {'name': payment_data.name}) - - if len(remove_payment) > 0: - for d in remove_payment: - si_doc.remove(d) - - si_doc.set_paid_amount() - si_doc.db_set("paid_amount", si_doc.paid_amount, update_modified = False) - si_doc.db_set("base_paid_amount", si_doc.base_paid_amount, update_modified = False) \ No newline at end of file diff --git a/erpnext/patches/v7_0/update_party_status.py b/erpnext/patches/v7_0/update_party_status.py deleted file mode 100644 index 0c6b4ea598d..00000000000 --- a/erpnext/patches/v7_0/update_party_status.py +++ /dev/null @@ -1,21 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - return - # for party_type in ('Customer', 'Supplier'): - # frappe.reload_doctype(party_type) - # - # # set all as default status - # frappe.db.sql('update `tab{0}` set status=%s'.format(party_type), default_status[party_type]) - # - # for doctype in status_depends_on[party_type]: - # filters = get_filters_for(doctype) - # parties = frappe.get_all(doctype, fields="{0} as party".format(party_type.lower()), - # filters=filters, limit_page_length=1) - # - # parties = filter(None, [p.party for p in parties]) - # - # if parties: - # frappe.db.sql('update `tab{0}` set status="Open" where name in ({1})'.format(party_type, - # ', '.join(len(parties) * ['%s'])), parties) \ No newline at end of file diff --git a/erpnext/patches/v7_0/update_prevdoc_values_for_supplier_quotation_item.py b/erpnext/patches/v7_0/update_prevdoc_values_for_supplier_quotation_item.py deleted file mode 100644 index e90de50c1ec..00000000000 --- a/erpnext/patches/v7_0/update_prevdoc_values_for_supplier_quotation_item.py +++ /dev/null @@ -1,9 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doctype('Supplier Quotation Item') - for data in frappe.db.sql(""" select prevdoc_docname, prevdoc_detail_docname, name - from `tabSupplier Quotation Item` where prevdoc_docname is not null""", as_dict=True): - frappe.db.set_value("Supplier Quotation Item", data.name, "material_request", data.prevdoc_docname) - frappe.db.set_value("Supplier Quotation Item", data.name, "material_request_item", data.prevdoc_detail_docname) \ No newline at end of file diff --git a/erpnext/patches/v7_0/update_project_in_gl_entry.py b/erpnext/patches/v7_0/update_project_in_gl_entry.py deleted file mode 100644 index d99e9a41e3b..00000000000 --- a/erpnext/patches/v7_0/update_project_in_gl_entry.py +++ /dev/null @@ -1,21 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doctype("GL Entry") - - for doctype in ("Delivery Note", "Sales Invoice", "Stock Entry"): - frappe.db.sql(""" - update `tabGL Entry` gle, `tab{0}` dt - set gle.project = dt.project - where gle.voucher_type=%s and gle.voucher_no = dt.name - and ifnull(gle.cost_center, '') != '' and ifnull(dt.project, '') != '' - """.format(doctype), doctype) - - for doctype in ("Purchase Receipt", "Purchase Invoice"): - frappe.db.sql(""" - update `tabGL Entry` gle, `tab{0} Item` dt - set gle.project = dt.project - where gle.voucher_type=%s and gle.voucher_no = dt.parent and gle.cost_center=dt.cost_center - and ifnull(gle.cost_center, '') != '' and ifnull(dt.project, '') != '' - """.format(doctype), doctype) \ No newline at end of file diff --git a/erpnext/patches/v7_0/update_refdoc_in_landed_cost_voucher.py b/erpnext/patches/v7_0/update_refdoc_in_landed_cost_voucher.py deleted file mode 100644 index 2d562bb40ec..00000000000 --- a/erpnext/patches/v7_0/update_refdoc_in_landed_cost_voucher.py +++ /dev/null @@ -1,15 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - if "purchase_receipt" not in frappe.db.get_table_columns("Landed Cost Purchase Receipt"): - return - - frappe.reload_doctype("Landed Cost Purchase Receipt") - - frappe.db.sql(""" - update `tabLanded Cost Purchase Receipt` - set receipt_document_type = 'Purchase Receipt', receipt_document = purchase_receipt - where (receipt_document is null or receipt_document = '') - and (purchase_receipt is not null and purchase_receipt != '') - """) \ No newline at end of file diff --git a/erpnext/patches/v7_0/update_status_for_timesheet.py b/erpnext/patches/v7_0/update_status_for_timesheet.py deleted file mode 100644 index 117c40c59f2..00000000000 --- a/erpnext/patches/v7_0/update_status_for_timesheet.py +++ /dev/null @@ -1,11 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.db.sql("""update - `tabTimesheet` as ts, - ( - select min(from_time)as from_time, max(to_time) as to_time, parent from `tabTimesheet Detail` group by parent - ) as tsd - set ts.status = 'Submitted', ts.start_date = tsd.from_time, ts.end_date = tsd.to_time - where tsd.parent = ts.name and ts.status = 'Draft' and ts.docstatus =1""") \ No newline at end of file diff --git a/erpnext/patches/v7_0/update_status_of_po_so.py b/erpnext/patches/v7_0/update_status_of_po_so.py deleted file mode 100644 index d630e8f0f2d..00000000000 --- a/erpnext/patches/v7_0/update_status_of_po_so.py +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe -from frappe.utils import cint, flt - -def execute(): - update_po_per_received_per_billed() - update_so_per_delivered_per_billed() - update_status() - -def update_po_per_received_per_billed(): - frappe.db.sql(""" - update - `tabPurchase Order` - set - `tabPurchase Order`.per_received = round((select sum(if(qty > ifnull(received_qty, 0), - ifnull(received_qty, 0), qty)) / sum(qty) *100 from `tabPurchase Order Item` - where parent = `tabPurchase Order`.name), 2), - `tabPurchase Order`.per_billed = ifnull(round((select sum( if(amount > ifnull(billed_amt, 0), - ifnull(billed_amt, 0), amount)) / sum(amount) *100 from `tabPurchase Order Item` - where parent = `tabPurchase Order`.name), 2), 0) - where - net_total > 0 - """) - -def update_so_per_delivered_per_billed(): - frappe.db.sql(""" - update - `tabSales Order` - set - `tabSales Order`.per_delivered = round((select sum( if(qty > ifnull(delivered_qty, 0), - ifnull(delivered_qty, 0), qty)) / sum(qty) *100 from `tabSales Order Item` - where parent = `tabSales Order`.name), 2), - `tabSales Order`.per_billed = ifnull(round((select sum( if(amount > ifnull(billed_amt, 0), - ifnull(billed_amt, 0), amount)) / sum(amount) *100 from `tabSales Order Item` - where parent = `tabSales Order`.name), 2), 0) - where - net_total > 0 - """) - -def update_status(): - frappe.db.sql(""" - update - `tabSales Order` - set status = (Case when status = 'Closed' then 'Closed' - When per_delivered < 100 and per_billed < 100 and docstatus = 1 then 'To Deliver and Bill' - when per_delivered = 100 and per_billed < 100 and docstatus = 1 then 'To Bill' - when per_delivered < 100 and per_billed = 100 and docstatus = 1 then 'To Deliver' - when per_delivered = 100 and per_billed = 100 and docstatus = 1 then 'Completed' - when order_type = 'Maintenance' and per_billed = 100 and docstatus = 1 then 'Completed' - when docstatus = 2 then 'Cancelled' - else 'Draft' - End)""") - - frappe.db.sql(""" - update - `tabPurchase Order` - set status = (Case when status = 'Closed' then 'Closed' - when status = 'Delivered' then 'Delivered' - When per_received < 100 and per_billed < 100 and docstatus = 1 then 'To Receive and Bill' - when per_received = 100 and per_billed < 100 and docstatus = 1 then 'To Bill' - when per_received < 100 and per_billed = 100 and docstatus = 1 then 'To Receive' - when per_received = 100 and per_billed = 100 and docstatus = 1 then 'Completed' - when docstatus = 2 then 'Cancelled' - else 'Draft' - End)""") \ No newline at end of file diff --git a/erpnext/patches/v7_0/update_status_of_zero_amount_sales_order.py b/erpnext/patches/v7_0/update_status_of_zero_amount_sales_order.py deleted file mode 100644 index 9b2b24785a5..00000000000 --- a/erpnext/patches/v7_0/update_status_of_zero_amount_sales_order.py +++ /dev/null @@ -1,7 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - for data in frappe.get_all('Sales Order', fields = ["name"], filters = [["docstatus", "=", "1"], ["grand_total", "=", "0"]]): - sales_order = frappe.get_doc('Sales Order', data.name) - sales_order.set_status(update=True, update_modified = False) \ No newline at end of file diff --git a/erpnext/patches/v7_0/update_timesheet_communications.py b/erpnext/patches/v7_0/update_timesheet_communications.py deleted file mode 100644 index 203471ea8f2..00000000000 --- a/erpnext/patches/v7_0/update_timesheet_communications.py +++ /dev/null @@ -1,27 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - if frappe.db.table_exists("Time Log"): - timesheet = frappe.db.sql("""SELECT ts.name AS name, tl.name AS timelogname, - tl.modified AS modified, tl.modified_by AS modified_by, tl.creation AS creation, tl.owner AS owner - FROM - `tabTimesheet` ts, `tabTimesheet Detail` tsd, `tabTime Log` tl - WHERE - tsd.parent = ts.name AND tl.from_time = tsd.from_time AND tl.to_time = tsd.to_time - AND tl.hours = tsd.hours AND tl.billing_rate = tsd.billing_rate AND tsd.idx=1 - AND tl.docstatus < 2""", as_dict=1) - - for data in timesheet: - frappe.db.sql(""" update `tabTimesheet` set creation = %(creation)s, - owner = %(owner)s, modified = %(modified)s, modified_by = %(modified_by)s - where name = %(name)s""", data) - - frappe.db.sql(""" - update - tabCommunication - set - reference_doctype = "Timesheet", reference_name = %(timesheet)s - where - reference_doctype = "Time Log" and reference_name = %(timelog)s - """, {'timesheet': data.name, 'timelog': data.timelogname}, auto_commit=1) diff --git a/erpnext/patches/v7_1/__init__.py b/erpnext/patches/v7_1/__init__.py deleted file mode 100644 index 519ff49eac1..00000000000 --- a/erpnext/patches/v7_1/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from __future__ import unicode_literals \ No newline at end of file diff --git a/erpnext/patches/v7_1/add_account_user_role_for_timesheet.py b/erpnext/patches/v7_1/add_account_user_role_for_timesheet.py deleted file mode 100644 index 7372b0cc5ff..00000000000 --- a/erpnext/patches/v7_1/add_account_user_role_for_timesheet.py +++ /dev/null @@ -1,31 +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 - -def execute(): - if not frappe.db.get_value('DocPerm', {'parent': 'Timesheet', 'role': 'Accounts User', 'permlevel': 1}): - doc = frappe.get_doc('DocType', 'Timesheet') - doc.append('permissions', { - 'role': "Accounts User", - 'permlevel': 0, - 'read': 1, - 'write': 1, - 'create': 1, - 'delete': 1, - 'submit': 1, - 'cancel': 1, - 'amend': 1, - 'report': 1, - 'email': 1 - }) - - doc.append('permissions', { - 'role': "Accounts User", - 'permlevel': 1, - 'read': 1, - 'write': 1 - }) - - doc.save(ignore_permissions=True) \ No newline at end of file diff --git a/erpnext/patches/v7_1/add_field_for_task_dependent.py b/erpnext/patches/v7_1/add_field_for_task_dependent.py deleted file mode 100644 index 65b1c74e87d..00000000000 --- a/erpnext/patches/v7_1/add_field_for_task_dependent.py +++ /dev/null @@ -1,10 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doctype('Task') - for t in frappe.get_all('Task', fields=['name']): - task = frappe.get_doc('Task', t.name) - task.update_depends_on() - if task.depends_on_tasks: - task.db_set('depends_on_tasks', task.depends_on_tasks, update_modified=False) diff --git a/erpnext/patches/v7_1/fix_link_for_customer_from_lead.py b/erpnext/patches/v7_1/fix_link_for_customer_from_lead.py deleted file mode 100644 index 33f809fe37e..00000000000 --- a/erpnext/patches/v7_1/fix_link_for_customer_from_lead.py +++ /dev/null @@ -1,7 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - for c in frappe.db.sql('select name from tabCustomer where ifnull(lead_name,"")!=""'): - customer = frappe.get_doc('Customer', c[0]) - customer.update_lead_status() \ No newline at end of file diff --git a/erpnext/patches/v7_1/move_sales_invoice_from_parent_to_child_timesheet.py b/erpnext/patches/v7_1/move_sales_invoice_from_parent_to_child_timesheet.py deleted file mode 100644 index d1ec7c697e7..00000000000 --- a/erpnext/patches/v7_1/move_sales_invoice_from_parent_to_child_timesheet.py +++ /dev/null @@ -1,20 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doc('projects', 'doctype', 'timesheet_detail') - frappe.reload_doc('accounts', 'doctype', 'sales_invoice_timesheet') - - frappe.db.sql(""" update - `tabTimesheet` as ts, - (select - sum(billing_amount) as billing_amount, sum(billing_hours) as billing_hours, time_sheet - from `tabSales Invoice Timesheet` where docstatus = 1 group by time_sheet - ) as sit - set - ts.total_billed_amount = sit.billing_amount, ts.total_billed_hours = sit.billing_hours, - ts.per_billed = ((sit.billing_amount * 100)/ts.total_billable_amount) - where ts.name = sit.time_sheet and ts.docstatus = 1""") - - frappe.db.sql(""" update `tabTimesheet Detail` tsd, `tabTimesheet` ts set tsd.sales_invoice = ts.sales_invoice - where tsd.parent = ts.name and ts.sales_invoice is not null""") \ No newline at end of file diff --git a/erpnext/patches/v7_1/rename_field_timesheet.py b/erpnext/patches/v7_1/rename_field_timesheet.py deleted file mode 100644 index 3690a2e79d4..00000000000 --- a/erpnext/patches/v7_1/rename_field_timesheet.py +++ /dev/null @@ -1,11 +0,0 @@ -from __future__ import unicode_literals -import frappe -from frappe.model.utils.rename_field import rename_field - -def execute(): - doctype = 'Timesheet' - fields_dict = {'total_billing_amount': 'total_billable_amount', 'total_billing_hours': 'total_billable_hours'} - - for old_fieldname, new_fieldname in fields_dict.items(): - if old_fieldname in frappe.db.get_table_columns(doctype): - rename_field(doctype, old_fieldname, new_fieldname) diff --git a/erpnext/patches/v7_1/rename_quality_inspection_field.py b/erpnext/patches/v7_1/rename_quality_inspection_field.py deleted file mode 100644 index 3b5a7d95eb1..00000000000 --- a/erpnext/patches/v7_1/rename_quality_inspection_field.py +++ /dev/null @@ -1,38 +0,0 @@ -from __future__ import unicode_literals -import frappe -from frappe.model.utils.rename_field import * - -def execute(): - for doctype in ("Purchase Receipt Item", "Delivery Note Item"): - frappe.reload_doctype(doctype) - - table_columns = frappe.db.get_table_columns(doctype) - if "qa_no" in table_columns: - rename_field(doctype, "qa_no", "quality_inspection") - - frappe.reload_doctype("Item") - rename_field("Item", "inspection_required", "inspection_required_before_purchase") - - frappe.reload_doc('stock', 'doctype', 'quality_inspection') - frappe.db.sql(""" - update - `tabQuality Inspection` - set - reference_type = 'Purchase Receipt', reference_name = purchase_receipt_no - where - ifnull(purchase_receipt_no, '') != '' and inspection_type = 'Incoming' - """) - - frappe.db.sql(""" - update - `tabQuality Inspection` - set - reference_type = 'Delivery Note', reference_name = delivery_note_no - where - ifnull(delivery_note_no, '') != '' and inspection_type = 'Outgoing' - """) - - for old_fieldname in ["purchase_receipt_no", "delivery_note_no"]: - update_reports("Quality Inspection", old_fieldname, "reference_name") - update_users_report_view_settings("Quality Inspection", old_fieldname, "reference_name") - update_property_setters("Quality Inspection", old_fieldname, "reference_name") diff --git a/erpnext/patches/v7_1/repost_stock_for_deleted_bins_for_merging_items.py b/erpnext/patches/v7_1/repost_stock_for_deleted_bins_for_merging_items.py deleted file mode 100644 index aca21085cc1..00000000000 --- a/erpnext/patches/v7_1/repost_stock_for_deleted_bins_for_merging_items.py +++ /dev/null @@ -1,44 +0,0 @@ -from __future__ import unicode_literals -import frappe -from erpnext.stock.stock_balance import repost_stock - -def execute(): - frappe.reload_doc('manufacturing', 'doctype', 'work_order_item') - frappe.reload_doc('manufacturing', 'doctype', 'work_order') - - modified_items = frappe.db.sql_list(""" - select name from `tabItem` - where is_stock_item=1 and modified >= '2016-10-31' - """) - - if not modified_items: - return - - item_warehouses_with_transactions = [] - transactions = ("Sales Order Item", "Material Request Item", "Purchase Order Item", - "Stock Ledger Entry", "Packed Item") - - for doctype in transactions: - item_warehouses_with_transactions += list(frappe.db.sql(""" - select distinct item_code, warehouse - from `tab{0}` where docstatus=1 and item_code in ({1})""" - .format(doctype, ', '.join(['%s']*len(modified_items))), tuple(modified_items))) - - item_warehouses_with_transactions += list(frappe.db.sql(""" - select distinct production_item, fg_warehouse - from `tabWork Order` where docstatus=1 and production_item in ({0})""" - .format(', '.join(['%s']*len(modified_items))), tuple(modified_items))) - - item_warehouses_with_transactions += list(frappe.db.sql(""" - select distinct pr_item.item_code, pr_item.source_warehouse - from `tabWork Order` pr, `tabWork Order Item` pr_item - where pr_item.parent and pr.name and pr.docstatus=1 and pr_item.item_code in ({0})""" - .format(', '.join(['%s']*len(modified_items))), tuple(modified_items))) - - item_warehouses_with_bin = list(frappe.db.sql("select distinct item_code, warehouse from `tabBin`")) - - item_warehouses_with_missing_bin = list( - set(item_warehouses_with_transactions) - set(item_warehouses_with_bin)) - - for item_code, warehouse in item_warehouses_with_missing_bin: - repost_stock(item_code, warehouse) diff --git a/erpnext/patches/v7_1/save_stock_settings.py b/erpnext/patches/v7_1/save_stock_settings.py deleted file mode 100644 index d3f0263c102..00000000000 --- a/erpnext/patches/v7_1/save_stock_settings.py +++ /dev/null @@ -1,15 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - stock_settings = frappe.get_doc('Stock Settings') - - if stock_settings.default_warehouse \ - and not frappe.db.exists("Warehouse", stock_settings.default_warehouse): - stock_settings.default_warehouse = None - - if stock_settings.stock_uom and not frappe.db.exists("UOM", stock_settings.stock_uom): - stock_settings.stock_uom = None - - stock_settings.flags.ignore_mandatory = True - stock_settings.save() diff --git a/erpnext/patches/v7_1/set_budget_against_as_cost_center.py b/erpnext/patches/v7_1/set_budget_against_as_cost_center.py deleted file mode 100644 index dd9a432cf01..00000000000 --- a/erpnext/patches/v7_1/set_budget_against_as_cost_center.py +++ /dev/null @@ -1,11 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doc("accounts", "doctype", "budget") - frappe.db.sql(""" - update - `tabBudget` - set - budget_against = 'Cost Center' - """) diff --git a/erpnext/patches/v7_1/set_currency_exchange_date.py b/erpnext/patches/v7_1/set_currency_exchange_date.py deleted file mode 100644 index 2a2d420f21c..00000000000 --- a/erpnext/patches/v7_1/set_currency_exchange_date.py +++ /dev/null @@ -1,10 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doctype("Currency Exchange") - frappe.db.sql(""" - update `tabCurrency Exchange` - set `date` = '2010-01-01' - where date is null or date = '0000-00-00' - """) \ No newline at end of file diff --git a/erpnext/patches/v7_1/set_prefered_contact_email.py b/erpnext/patches/v7_1/set_prefered_contact_email.py deleted file mode 100644 index 3b68e22269a..00000000000 --- a/erpnext/patches/v7_1/set_prefered_contact_email.py +++ /dev/null @@ -1,17 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doctype('User') - for d in frappe.get_all("Employee"): - employee = frappe.get_doc("Employee", d.name) - if employee.company_email: - employee.prefered_contact_email = "Company Email" - employee.prefered_email = employee.company_email - elif employee.personal_email: - employee.prefered_contact_email = "Personal Email" - employee.prefered_email = employee.personal_email - elif employee.user_id: - employee.prefered_contact_email = "User ID" - employee.prefered_email = employee.user_id - employee.db_update() diff --git a/erpnext/patches/v7_1/set_sales_person_status.py b/erpnext/patches/v7_1/set_sales_person_status.py deleted file mode 100644 index 929beac27f4..00000000000 --- a/erpnext/patches/v7_1/set_sales_person_status.py +++ /dev/null @@ -1,8 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doc('setup','doctype','sales_person') - frappe.db.sql("""update `tabSales Person` set enabled=1 - where (employee is null or employee = '' - or employee IN (select employee from tabEmployee where status != "Left"))""") diff --git a/erpnext/patches/v7_1/set_student_guardian.py b/erpnext/patches/v7_1/set_student_guardian.py deleted file mode 100644 index 093c0bf6d94..00000000000 --- a/erpnext/patches/v7_1/set_student_guardian.py +++ /dev/null @@ -1,23 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - if frappe.db.exists("DocType", "Guardian"): - - # 'Schools' module changed to the 'Education' - # frappe.reload_doc("schools", "doctype", "student") - # frappe.reload_doc("schools", "doctype", "student_guardian") - # frappe.reload_doc("schools", "doctype", "student_sibling") - - frappe.reload_doc("education", "doctype", "student") - frappe.reload_doc("education", "doctype", "student_guardian") - frappe.reload_doc("education", "doctype", "student_sibling") - if "student" not in frappe.db.get_table_columns("Guardian"): - return - guardian = frappe.get_all("Guardian", fields=["name", "student"]) - for d in guardian: - if d.student: - student = frappe.get_doc("Student", d.student) - if student: - student.append("guardians", {"guardian": d.name}) - student.save() diff --git a/erpnext/patches/v7_1/set_total_amount_currency_in_je.py b/erpnext/patches/v7_1/set_total_amount_currency_in_je.py deleted file mode 100644 index 8426ddcd7d9..00000000000 --- a/erpnext/patches/v7_1/set_total_amount_currency_in_je.py +++ /dev/null @@ -1,24 +0,0 @@ -from __future__ import unicode_literals -import frappe -from erpnext import get_default_currency - -def execute(): - frappe.reload_doc("accounts", "doctype", "journal_entry") - - frappe.db.sql(""" update `tabJournal Entry` set total_amount_currency = %s - where ifnull(multi_currency, 0) = 0 - and (pay_to_recd_from is not null or pay_to_recd_from != "") """, get_default_currency()) - - for je in frappe.db.sql(""" select name from `tabJournal Entry` where multi_currency = 1 - and (pay_to_recd_from is not null or pay_to_recd_from != "")""", as_dict=1): - - doc = frappe.get_doc("Journal Entry", je.name) - for d in doc.get('accounts'): - if d.party_type and d.party: - total_amount_currency = d.account_currency - - elif frappe.db.get_value("Account", d.account, "account_type") in ["Bank", "Cash"]: - total_amount_currency = d.account_currency - - frappe.db.set_value("Journal Entry", je.name, "total_amount_currency", - total_amount_currency, update_modified=False) diff --git a/erpnext/patches/v7_1/update_bom_base_currency.py b/erpnext/patches/v7_1/update_bom_base_currency.py deleted file mode 100644 index 9a59209ea52..00000000000 --- a/erpnext/patches/v7_1/update_bom_base_currency.py +++ /dev/null @@ -1,20 +0,0 @@ -from __future__ import unicode_literals -import frappe -from erpnext import get_default_currency - -def execute(): - frappe.reload_doc("manufacturing", "doctype", "bom") - frappe.reload_doc("manufacturing", "doctype", "bom_item") - frappe.reload_doc("manufacturing", "doctype", "bom_explosion_item") - frappe.reload_doc("manufacturing", "doctype", "bom_operation") - frappe.reload_doc("manufacturing", "doctype", "bom_scrap_item") - - frappe.db.sql(""" update `tabBOM Operation` set base_hour_rate = hour_rate, - base_operating_cost = operating_cost """) - - frappe.db.sql(""" update `tabBOM Item` set base_rate = rate, base_amount = amount """) - frappe.db.sql(""" update `tabBOM Scrap Item` set base_rate = rate, base_amount = amount """) - - frappe.db.sql(""" update `tabBOM` set `tabBOM`.base_operating_cost = `tabBOM`.operating_cost, - `tabBOM`.base_raw_material_cost = `tabBOM`.raw_material_cost, - `tabBOM`.currency = (select default_currency from `tabCompany` where name = `tabBOM`.company)""") diff --git a/erpnext/patches/v7_1/update_component_type.py b/erpnext/patches/v7_1/update_component_type.py deleted file mode 100644 index 24ca0570e01..00000000000 --- a/erpnext/patches/v7_1/update_component_type.py +++ /dev/null @@ -1,15 +0,0 @@ -from __future__ import unicode_literals -import frappe -from frappe.utils import flt - -def execute(): - frappe.reload_doc('Payroll', 'doctype', 'salary_component') - sal_components = frappe.db.sql(""" - select DISTINCT salary_component, parentfield from `tabSalary Detail`""", as_dict=True) - - if sal_components: - for sal_component in sal_components: - if sal_component.parentfield == "earnings": - frappe.db.sql("""update `tabSalary Component` set type='Earning' where salary_component=%(sal_comp)s""",{"sal_comp": sal_component.salary_component}) - else: - frappe.db.sql("""update `tabSalary Component` set type='Deduction' where salary_component=%(sal_comp)s""",{"sal_comp": sal_component.salary_component}) \ No newline at end of file diff --git a/erpnext/patches/v7_1/update_invoice_status.py b/erpnext/patches/v7_1/update_invoice_status.py deleted file mode 100644 index 851af80f7a2..00000000000 --- a/erpnext/patches/v7_1/update_invoice_status.py +++ /dev/null @@ -1,34 +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 - -def execute(): - frappe.reload_doc('accounts', 'doctype', 'sales_invoice') - frappe.reload_doc('accounts', 'doctype', 'purchase_invoice') - - frappe.db.sql(""" - update - `tabPurchase Invoice` - set - status = (Case When outstanding_amount = 0 and docstatus = 1 and is_return = 0 then 'Paid' - when due_date < CURDATE() and outstanding_amount > 0 and docstatus =1 then 'Overdue' - when due_date >= CURDATE() and outstanding_amount > 0 and docstatus =1 then 'Unpaid' - when outstanding_amount < 0 and docstatus =1 then 'Debit Note Issued' - when is_return = 1 and docstatus =1 then 'Return' - when docstatus = 2 then 'Cancelled' - else 'Draft' - End)""") - - frappe.db.sql(""" - update - `tabSales Invoice` - set status = (Case When outstanding_amount = 0 and docstatus = 1 and is_return = 0 then 'Paid' - when due_date < CURDATE() and outstanding_amount > 0 and docstatus =1 then 'Overdue' - when due_date >= CURDATE() and outstanding_amount > 0 and docstatus =1 then 'Unpaid' - when outstanding_amount < 0 and docstatus =1 then 'Credit Note Issued' - when is_return = 1 and docstatus =1 then 'Return' - when docstatus = 2 then 'Cancelled' - else 'Draft' - End)""") \ No newline at end of file diff --git a/erpnext/patches/v7_1/update_lead_source.py b/erpnext/patches/v7_1/update_lead_source.py deleted file mode 100644 index a2a48a62e1a..00000000000 --- a/erpnext/patches/v7_1/update_lead_source.py +++ /dev/null @@ -1,29 +0,0 @@ -from __future__ import unicode_literals -import frappe -from frappe import _ - -def execute(): - from erpnext.setup.setup_wizard.operations.install_fixtures import default_lead_sources - - frappe.reload_doc('crm', 'doctype', 'lead_source') - - frappe.local.lang = frappe.db.get_default("lang") or 'en' - - for s in default_lead_sources: - insert_lead_source(_(s)) - - # get lead sources in existing forms (customized) - # and create a document if not created - for d in ['Lead', 'Opportunity', 'Quotation', 'Sales Order', 'Delivery Note', 'Sales Invoice']: - sources = frappe.db.sql_list('select distinct source from `tab{0}`'.format(d)) - for s in sources: - if s and s not in default_lead_sources: - insert_lead_source(s) - - # remove customization for source - for p in frappe.get_all('Property Setter', {'doc_type':d, 'field_name':'source', 'property':'options'}): - frappe.delete_doc('Property Setter', p.name) - -def insert_lead_source(s): - if not frappe.db.exists('Lead Source', s): - frappe.get_doc(dict(doctype='Lead Source', source_name=s)).insert() diff --git a/erpnext/patches/v7_1/update_missing_salary_component_type.py b/erpnext/patches/v7_1/update_missing_salary_component_type.py deleted file mode 100644 index 824f2b881f0..00000000000 --- a/erpnext/patches/v7_1/update_missing_salary_component_type.py +++ /dev/null @@ -1,50 +0,0 @@ -from __future__ import unicode_literals - -import frappe -from frappe.utils import cstr - -''' -Some components do not have type set, try and guess whether they turn up in -earnings or deductions in existing salary slips -''' - -def execute(): - frappe.reload_doc("accounts", "doctype", "salary_component_account") - frappe.reload_doc("Payroll", "doctype", "salary_component") - frappe.reload_doc("Payroll", "doctype", "taxable_salary_slab") - - for s in frappe.db.sql('''select name, type, salary_component_abbr from `tabSalary Component` - where ifnull(type, "")="" or ifnull(salary_component_abbr, "") = ""''', as_dict=1): - - component = frappe.get_doc('Salary Component', s.name) - - # guess - if not s.type: - guess = frappe.db.sql('''select - parentfield from `tabSalary Detail` - where salary_component=%s limit 1''', s.name) - - if guess: - component.type = 'Earning' if guess[0][0]=='earnings' else 'Deduction' - - else: - component.type = 'Deduction' - - if not s.salary_component_abbr: - abbr = ''.join([c[0] for c in component.salary_component.split()]).upper() - - abbr_count = frappe.db.sql(""" - select - count(name) - from - `tabSalary Component` - where - salary_component_abbr = %s or salary_component_abbr like %s - """, (abbr, abbr + "-%%")) - - if abbr_count and abbr_count[0][0] > 0: - abbr = abbr + "-" + cstr(abbr_count[0][0]) - - component.salary_component_abbr = abbr - - component.save() diff --git a/erpnext/patches/v7_1/update_portal_roles.py b/erpnext/patches/v7_1/update_portal_roles.py deleted file mode 100644 index 482586b8efe..00000000000 --- a/erpnext/patches/v7_1/update_portal_roles.py +++ /dev/null @@ -1,21 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doctype('Role') - frappe.reload_doctype('User') - for role_name in ('Customer', 'Supplier', 'Student'): - if frappe.db.exists('Role', role_name): - frappe.db.set_value('Role', role_name, 'desk_access', 0) - else: - frappe.get_doc(dict(doctype='Role', role_name=role_name, desk_access=0)).insert() - - - # set customer, supplier roles - for c in frappe.get_all('Contact', fields=['user'], filters={'ifnull(user, "")': ('!=', '')}): - user = frappe.get_doc('User', c.user) - user.flags.ignore_validate = True - user.flags.ignore_mandatory = True - user.save() - - diff --git a/erpnext/patches/v7_1/update_total_billing_hours.py b/erpnext/patches/v7_1/update_total_billing_hours.py deleted file mode 100644 index b9c96028f52..00000000000 --- a/erpnext/patches/v7_1/update_total_billing_hours.py +++ /dev/null @@ -1,14 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doc('projects', 'doctype', 'timesheet_detail') - frappe.reload_doc('accounts', 'doctype', 'sales_invoice_timesheet') - - frappe.db.sql("""update tabTimesheet set total_billable_hours=total_hours - where total_billable_amount>0 and docstatus = 1""") - - frappe.db.sql("""update `tabTimesheet Detail` set billing_hours=hours where docstatus < 2""") - - frappe.db.sql(""" update `tabSales Invoice Timesheet` set billing_hours = (select total_billable_hours from `tabTimesheet` - where name = time_sheet) where time_sheet is not null""") \ No newline at end of file diff --git a/erpnext/patches/v7_2/__init__.py b/erpnext/patches/v7_2/__init__.py deleted file mode 100644 index baffc488252..00000000000 --- a/erpnext/patches/v7_2/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from __future__ import unicode_literals diff --git a/erpnext/patches/v7_2/arrear_leave_encashment_as_salary_component.py b/erpnext/patches/v7_2/arrear_leave_encashment_as_salary_component.py deleted file mode 100644 index d2583b94224..00000000000 --- a/erpnext/patches/v7_2/arrear_leave_encashment_as_salary_component.py +++ /dev/null @@ -1,36 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - # frappe.reload_doctype('Salary Slip', 'Salary Component') - frappe.reload_doc("Payroll", "doctype", "Salary Slip") - frappe.reload_doc("Payroll", "doctype", "Salary Component") - salary_components = [['Arrear', "ARR"], ['Leave Encashment', 'LENC']] - for salary_component, salary_abbr in salary_components: - if not frappe.db.exists('Salary Component', salary_component): - sal_comp = frappe.get_doc({ - "doctype": "Salary Component", - "salary_component": salary_component, - "type": "Earning", - "salary_component_abbr": salary_abbr - }).insert() - - salary_slips = frappe.db.sql("""select name, arrear_amount, leave_encashment_amount from `tabSalary Slip` - where docstatus !=2 and (arrear_amount > 0 or leave_encashment_amount > 0)""", as_dict=True) - - for salary_slip in salary_slips: - doc = frappe.get_doc('Salary Slip', salary_slip.name) - - if salary_slip.get("arrear_amount") > 0: - r = doc.append('earnings', { - 'salary_component': 'Arrear', - 'amount': salary_slip.arrear_amount - }) - r.db_update() - - if salary_slip.get("leave_encashment_amount") > 0: - r = doc.append('earnings', { - 'salary_component': 'Leave Encashment', - 'amount': salary_slip.leave_encashment_amount - }) - r.db_update() \ No newline at end of file diff --git a/erpnext/patches/v7_2/contact_address_links.py b/erpnext/patches/v7_2/contact_address_links.py deleted file mode 100644 index 200434c208d..00000000000 --- a/erpnext/patches/v7_2/contact_address_links.py +++ /dev/null @@ -1,32 +0,0 @@ -from __future__ import unicode_literals -import frappe -from frappe.core.doctype.dynamic_link.dynamic_link import deduplicate_dynamic_links -from frappe.utils import update_progress_bar - -def execute(): - frappe.reload_doc('core', 'doctype', 'dynamic_link') - frappe.reload_doc('contacts', 'doctype', 'contact') - frappe.reload_doc('contacts', 'doctype', 'address') - map_fields = ( - ('Customer', 'customer'), - ('Supplier', 'supplier'), - ('Lead', 'lead'), - ('Sales Partner', 'sales_partner') - ) - for doctype in ('Contact', 'Address'): - if frappe.db.has_column(doctype, 'customer'): - items = frappe.get_all(doctype) - for i, doc in enumerate(items): - doc = frappe.get_doc(doctype, doc.name) - dirty = False - for field in map_fields: - if doc.get(field[1]): - doc.append('links', dict(link_doctype=field[0], link_name=doc.get(field[1]))) - dirty = True - - if dirty: - deduplicate_dynamic_links(doc) - doc.update_children() - - update_progress_bar('Updating {0}'.format(doctype), i, len(items)) - print \ No newline at end of file diff --git a/erpnext/patches/v7_2/delete_fleet_management_module_def.py b/erpnext/patches/v7_2/delete_fleet_management_module_def.py deleted file mode 100644 index 542ac11e3f2..00000000000 --- a/erpnext/patches/v7_2/delete_fleet_management_module_def.py +++ /dev/null @@ -1,10 +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 - -def execute(): - if frappe.db.exists('Module Def', 'Fleet Management'): - frappe.db.sql("""delete from `tabModule Def` - where module_name = 'Fleet Management'""") \ No newline at end of file diff --git a/erpnext/patches/v7_2/empty_supplied_items_for_non_subcontracted.py b/erpnext/patches/v7_2/empty_supplied_items_for_non_subcontracted.py deleted file mode 100644 index ec6f8afc3a5..00000000000 --- a/erpnext/patches/v7_2/empty_supplied_items_for_non_subcontracted.py +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - for doctype in ["Purchase Order", "Purchase Invoice", "Purchase Receipt"]: - child_table = 'Purchase Receipt Item Supplied' if doctype != 'Purchase Order' else 'Purchase Order Item Supplied' - for data in frappe.db.sql(""" select distinct `tab{doctype}`.name from `tab{doctype}` , `tab{child_table}` - where `tab{doctype}`.name = `tab{child_table}`.parent and `tab{doctype}`.docstatus != 2 - and `tab{doctype}`.is_subcontracted = 'No' """.format(doctype = doctype, child_table = child_table), as_dict=1): - frappe.db.sql(""" delete from `tab{child_table}` - where parent = %s and parenttype = %s""".format(child_table= child_table), (data.name, doctype)) \ No newline at end of file diff --git a/erpnext/patches/v7_2/make_all_assessment_group.py b/erpnext/patches/v7_2/make_all_assessment_group.py deleted file mode 100644 index f3ec628374c..00000000000 --- a/erpnext/patches/v7_2/make_all_assessment_group.py +++ /dev/null @@ -1,14 +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 - -def execute(): - if not frappe.db.exists({"doctype": "Assessment Group","assessment_group_name": "All Assessment Groups"}): - frappe.reload_doc("education", "doctype", "assessment_group") - doc = frappe.new_doc("Assessment Group") - doc.assessment_group_name = "All Assessment Groups" - doc.is_group = 1 - doc.flags.ignore_mandatory = True - doc.save() \ No newline at end of file diff --git a/erpnext/patches/v7_2/mark_students_active.py b/erpnext/patches/v7_2/mark_students_active.py deleted file mode 100644 index 7289e4a9158..00000000000 --- a/erpnext/patches/v7_2/mark_students_active.py +++ /dev/null @@ -1,9 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - # 'Schools' module changed to the 'Education' - # frappe.reload_doc('schools', 'doctype', 'student_group_student') - - frappe.reload_doc('education', 'doctype', 'student_group_student') - frappe.db.sql("update `tabStudent Group Student` set active=1") diff --git a/erpnext/patches/v7_2/rename_att_date_attendance.py b/erpnext/patches/v7_2/rename_att_date_attendance.py deleted file mode 100644 index 7f06d8f1239..00000000000 --- a/erpnext/patches/v7_2/rename_att_date_attendance.py +++ /dev/null @@ -1,15 +0,0 @@ -from __future__ import unicode_literals -import frappe -from frappe.model.utils.rename_field import update_reports, update_users_report_view_settings, update_property_setters - -def execute(): - if "att_date" not in frappe.db.get_table_columns("Attendance"): - return - frappe.reload_doc("hr", "doctype", "attendance") - frappe.db.sql("""update `tabAttendance` - set attendance_date = att_date - where attendance_date is null or attendance_date = '0000-00-00'""") - - update_reports("Attendance", "att_date", "attendance_date") - update_users_report_view_settings("Attendance", "att_date", "attendance_date") - update_property_setters("Attendance", "att_date", "attendance_date") diff --git a/erpnext/patches/v7_2/rename_evaluation_criteria.py b/erpnext/patches/v7_2/rename_evaluation_criteria.py deleted file mode 100644 index c6520b1b725..00000000000 --- a/erpnext/patches/v7_2/rename_evaluation_criteria.py +++ /dev/null @@ -1,39 +0,0 @@ -from __future__ import unicode_literals -import frappe -from frappe.model.utils.rename_field import rename_field - -def execute(): - # 'Schools' module changed to the 'Education' - - - frappe.rename_doc("DocType", "Evaluation Criteria", "Assessment Criteria", force=True) - # frappe.reload_doc("schools", "doctype", "assessment_criteria") - frappe.reload_doc("education", "doctype", "assessment_criteria") - if 'evaluation_criteria' in frappe.db.get_table_columns('Assessment Criteria'): - rename_field("Assessment Criteria", "evaluation_criteria", "assessment_criteria") - - frappe.rename_doc("DocType", "Assessment Evaluation Criteria", "Assessment Plan Criteria", force=True) - # frappe.reload_doc("schools", "doctype", "assessment_plan_criteria") - frappe.reload_doc("education", "doctype", "assessment_plan_criteria") - if 'evaluation_criteria' in frappe.db.get_table_columns('Assessment Plan'): - rename_field("Assessment Plan Criteria", "evaluation_criteria", "assessment_criteria") - - # frappe.reload_doc("schools", "doctype", "assessment_plan") - frappe.reload_doc("education", "doctype", "assessment_plan") - rename_field("Assessment Plan", "evaluation_criterias", "assessment_criteria") - - # frappe.reload_doc("schools", "doctype", "assessment_result_detail") - frappe.reload_doc("education", "doctype", "assessment_result_detail") - if 'evaluation_criteria' in frappe.db.get_table_columns('Assessment Result Detail'): - rename_field("Assessment Result Detail", "evaluation_criteria", "assessment_criteria") - - frappe.rename_doc("DocType", "Course Evaluation Criteria", "Course Assessment Criteria", force=True) - # frappe.reload_doc("schools", "doctype", "course_assessment_criteria") - frappe.reload_doc("education", "doctype", "course_assessment_criteria") - if 'evaluation_criteria' in frappe.db.get_table_columns('Course Assessment Criteria'): - rename_field("Course Assessment Criteria", "evaluation_criteria", "assessment_criteria") - - # frappe.reload_doc("schools", "doctype", "course") - frappe.reload_doc("education", "doctype", "course") - if 'evaluation_criteria' in frappe.db.get_table_columns('Course'): - rename_field("Course", "evaluation_criterias", "assessment_criteria") diff --git a/erpnext/patches/v7_2/set_null_value_to_fields.py b/erpnext/patches/v7_2/set_null_value_to_fields.py deleted file mode 100644 index 6388be438db..00000000000 --- a/erpnext/patches/v7_2/set_null_value_to_fields.py +++ /dev/null @@ -1,11 +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 - -def execute(): - fields = {"Cost Center": "project", "Project": "cost_center"} - for budget_against, field in fields.items(): - frappe.db.sql(""" update `tabBudget` set {field} = null - where budget_against = %s """.format(field = field), budget_against) diff --git a/erpnext/patches/v7_2/setup_auto_close_settings.py b/erpnext/patches/v7_2/setup_auto_close_settings.py deleted file mode 100644 index 4eef2b9c8a7..00000000000 --- a/erpnext/patches/v7_2/setup_auto_close_settings.py +++ /dev/null @@ -1,18 +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 - -def execute(): - # update the selling settings and set the close_opportunity_after_days - frappe.reload_doc("selling", "doctype", "selling_settings") - frappe.db.set_value("Selling Settings", "Selling Settings", "close_opportunity_after_days", 15) - - # Auto close Replied opportunity - frappe.db.sql("""update `tabOpportunity` set status='Closed' where status='Replied' - and date_sub(curdate(), interval 15 Day)>modified""") - - # create Support Settings doctype and update close_issue_after_days - frappe.reload_doc("support", "doctype", "support_settings") - frappe.db.set_value("Support Settings", "Support Settings", "close_issue_after_days", 7) \ No newline at end of file diff --git a/erpnext/patches/v7_2/stock_uom_in_selling.py b/erpnext/patches/v7_2/stock_uom_in_selling.py deleted file mode 100644 index d0295557470..00000000000 --- a/erpnext/patches/v7_2/stock_uom_in_selling.py +++ /dev/null @@ -1,15 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doctype('Sales Order') - frappe.reload_doctype('Sales Invoice') - frappe.reload_doctype('Quotation') - frappe.reload_doctype('Delivery Note') - - doctype_list = ['Sales Order Item', 'Delivery Note Item', 'Quotation Item', 'Sales Invoice Item'] - - for doctype in doctype_list: - frappe.reload_doctype(doctype) - frappe.db.sql("""update `tab{doctype}` - set uom = stock_uom, conversion_factor = 1, stock_qty = qty""".format(doctype=doctype)) \ No newline at end of file diff --git a/erpnext/patches/v7_2/update_abbr_in_salary_slips.py b/erpnext/patches/v7_2/update_abbr_in_salary_slips.py deleted file mode 100644 index 57432fe9861..00000000000 --- a/erpnext/patches/v7_2/update_abbr_in_salary_slips.py +++ /dev/null @@ -1,14 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doc('Payroll', 'doctype', 'Salary Slip') - if not frappe.db.has_column('Salary Detail', 'abbr'): - return - - salary_details = frappe.db.sql("""select abbr, salary_component, name from `tabSalary Detail` - where abbr is null or abbr = ''""", as_dict=True) - - for salary_detail in salary_details: - salary_component_abbr = frappe.get_value("Salary Component", salary_detail.salary_component, "salary_component_abbr") - frappe.db.sql("""update `tabSalary Detail` set abbr = %s where name = %s""",(salary_component_abbr, salary_detail.name)) \ No newline at end of file diff --git a/erpnext/patches/v7_2/update_assessment_modules.py b/erpnext/patches/v7_2/update_assessment_modules.py deleted file mode 100644 index 2b5e774d467..00000000000 --- a/erpnext/patches/v7_2/update_assessment_modules.py +++ /dev/null @@ -1,51 +0,0 @@ -from __future__ import unicode_literals -import frappe -from frappe.model.utils.rename_field import rename_field - -def execute(): - #Rename Grading Structure to Grading Scale - if not frappe.db.exists("DocType", "Grading Scale"): - frappe.rename_doc("DocType", "Grading Structure", "Grading Scale", force=True) - if not frappe.db.exists("DocType", "Grading Scale Interval"): - frappe.rename_doc("DocType", "Grade Interval", "Grading Scale Interval", force=True) - - # frappe.reload_doc("schools", "doctype", "grading_scale_interval") - frappe.reload_doc("education", "doctype", "grading_scale_interval") - if "to_score" in frappe.db.get_table_columns("Grading Scale Interval"): - rename_field("Grading Scale Interval", "to_score", "threshold") - - if not frappe.db.exists("DocType", "Assessment Plan"): - frappe.rename_doc("DocType", "Assessment", "Assessment Plan", force=True) - - # 'Schools' module changed to the 'Education' - # frappe.reload_doc("schools", "doctype", "assessment_plan") - - #Rename Assessment Results - frappe.reload_doc("education", "doctype", "assessment_plan") - if "grading_structure" in frappe.db.get_table_columns("Assessment Plan"): - rename_field("Assessment Plan", "grading_structure", "grading_scale") - - # frappe.reload_doc("schools", "doctype", "assessment_result") - # frappe.reload_doc("schools", "doctype", "assessment_result_detail") - # frappe.reload_doc("schools", "doctype", "assessment_criteria") - frappe.reload_doc("education", "doctype", "assessment_result") - frappe.reload_doc("education", "doctype", "assessment_result_detail") - frappe.reload_doc("education", "doctype", "assessment_criteria") - - - for assessment in frappe.get_all("Assessment Plan", - fields=["name", "grading_scale"], filters = [["docstatus", "!=", 2 ]]): - for stud_result in frappe.db.sql("select * from `tabAssessment Result` where parent= %s", - assessment.name, as_dict=True): - if stud_result.result: - assessment_result = frappe.new_doc("Assessment Result") - assessment_result.student = stud_result.student - assessment_result.student_name = stud_result.student_name - assessment_result.assessment_plan = assessment.name - assessment_result.grading_scale = assessment.grading_scale - assessment_result.total_score = stud_result.result - assessment_result.flags.ignore_validate = True - assessment_result.flags.ignore_mandatory = True - assessment_result.save() - - frappe.db.sql("""delete from `tabAssessment Result` where parent != '' or parent is not null""") \ No newline at end of file diff --git a/erpnext/patches/v7_2/update_attendance_docstatus.py b/erpnext/patches/v7_2/update_attendance_docstatus.py deleted file mode 100644 index a69052657dd..00000000000 --- a/erpnext/patches/v7_2/update_attendance_docstatus.py +++ /dev/null @@ -1,10 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doc("education", "doctype", "student_attendance") - frappe.db.sql(''' - update `tabStudent Attendance` set - docstatus=0 - where - docstatus=1''') \ No newline at end of file diff --git a/erpnext/patches/v7_2/update_doctype_status.py b/erpnext/patches/v7_2/update_doctype_status.py deleted file mode 100644 index c66f3f2e73a..00000000000 --- a/erpnext/patches/v7_2/update_doctype_status.py +++ /dev/null @@ -1,11 +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 - -def execute(): - doctypes = ["Opportunity", "Quotation", "Sales Order", "Sales Invoice", "Purchase Invoice", "Purchase Order", "Delivery Note", "Purchase Receipt"] - for doctype in doctypes: - frappe.db.sql(""" update `tab{doctype}` set status = 'Draft' - where status = 'Cancelled' and docstatus = 0 """.format(doctype = doctype)) \ No newline at end of file diff --git a/erpnext/patches/v7_2/update_guardian_name_in_student_master.py b/erpnext/patches/v7_2/update_guardian_name_in_student_master.py deleted file mode 100644 index 9f589ef00e1..00000000000 --- a/erpnext/patches/v7_2/update_guardian_name_in_student_master.py +++ /dev/null @@ -1,14 +0,0 @@ -from __future__ import unicode_literals -import frappe -from frappe.model.utils.rename_field import rename_field - -def execute(): - # 'Schools' module changed to the 'Education' - # frappe.reload_doc("schools", "doctype", "student_guardian") - frappe.reload_doc("education", "doctype", "student_guardian") - - student_guardians = frappe.get_all("Student Guardian", fields=["guardian"]) - for student_guardian in student_guardians: - guardian_name = frappe.db.get_value("Guardian", student_guardian.guardian, "guardian_name") - frappe.db.sql("update `tabStudent Guardian` set guardian_name = %s where guardian= %s", - (guardian_name, student_guardian.guardian)) \ No newline at end of file diff --git a/erpnext/patches/v7_2/update_party_type.py b/erpnext/patches/v7_2/update_party_type.py deleted file mode 100644 index 147f5a36435..00000000000 --- a/erpnext/patches/v7_2/update_party_type.py +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doc('setup', 'doctype', 'party_type') - make_party_type() - -def make_party_type(): - for party_type in ["Customer", "Supplier", "Employee"]: - if not frappe.db.get_value("Party Type", party_type): - doc = frappe.new_doc("Party Type") - doc.party_type = party_type - doc.save(ignore_permissions=True) \ No newline at end of file diff --git a/erpnext/patches/v7_2/update_salary_slips.py b/erpnext/patches/v7_2/update_salary_slips.py deleted file mode 100644 index 9fcce62d8ff..00000000000 --- a/erpnext/patches/v7_2/update_salary_slips.py +++ /dev/null @@ -1,22 +0,0 @@ -from __future__ import unicode_literals -import frappe -from erpnext.payroll.doctype.payroll_entry.payroll_entry import get_month_details -from frappe.utils import cint - -def execute(): - frappe.reload_doc("Payroll", "doctype", "Salary Slip") - if not frappe.db.has_column('Salary Slip', 'fiscal_year'): - return - - salary_slips = frappe.db.sql("""select month, name, fiscal_year from `tabSalary Slip` - where (month is not null and month != '') and - start_date is null and end_date is null and docstatus != 2""", as_dict=True) - - for salary_slip in salary_slips: - if not cint(salary_slip.month): - continue - get_start_end_date = get_month_details(salary_slip.fiscal_year, cint(salary_slip.month)) - start_date = get_start_end_date['month_start_date'] - end_date = get_start_end_date['month_end_date'] - frappe.db.sql("""update `tabSalary Slip` set start_date = %s, end_date = %s where name = %s""", - (start_date, end_date, salary_slip.name)) \ No newline at end of file diff --git a/erpnext/patches/v7_2/update_website_for_variant.py b/erpnext/patches/v7_2/update_website_for_variant.py deleted file mode 100644 index e8eef6e7da1..00000000000 --- a/erpnext/patches/v7_2/update_website_for_variant.py +++ /dev/null @@ -1,13 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - # variant must have show_in_website = 0 - frappe.reload_doctype('Item') - frappe.db.sql(''' - update tabItem set - show_variant_in_website = 1, - show_in_website = 0 - where - show_in_website=1 - and ifnull(variant_of, "")!=""''') \ No newline at end of file diff --git a/erpnext/patches/v8_0/__init__.py b/erpnext/patches/v8_0/__init__.py deleted file mode 100644 index baffc488252..00000000000 --- a/erpnext/patches/v8_0/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from __future__ import unicode_literals diff --git a/erpnext/patches/v8_0/addresses_linked_to_lead.py b/erpnext/patches/v8_0/addresses_linked_to_lead.py deleted file mode 100644 index b5f22342284..00000000000 --- a/erpnext/patches/v8_0/addresses_linked_to_lead.py +++ /dev/null @@ -1,5 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.db.sql("""UPDATE `tabDynamic Link` SET link_doctype = 'Lead' WHERE link_doctype = 'Load'""") diff --git a/erpnext/patches/v8_0/change_in_words_varchar_length.py b/erpnext/patches/v8_0/change_in_words_varchar_length.py deleted file mode 100644 index 68ff95b5ed7..00000000000 --- a/erpnext/patches/v8_0/change_in_words_varchar_length.py +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - doctypes = frappe.db.sql_list("""select parent from tabDocField where fieldname = 'in_words'""") - - for dt in doctypes: - for fieldname in ("in_words", "base_in_words"): - frappe.db.sql("alter table `tab{0}` change column `{1}` `{2}` varchar(255)" - .format(dt, fieldname, fieldname)) - - frappe.db.sql("""alter table `tabJournal Entry` - change column `total_amount_in_words` `total_amount_in_words` varchar(255)""") diff --git a/erpnext/patches/v8_0/create_address_doc_from_address_field_in_company.py b/erpnext/patches/v8_0/create_address_doc_from_address_field_in_company.py deleted file mode 100644 index cf1bc5af057..00000000000 --- a/erpnext/patches/v8_0/create_address_doc_from_address_field_in_company.py +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - # new field address_html is created in place of address field for the company's address in PR #8754 (without patch) - # so here is the patch for moving the address details in the address doc - company_list = [] - if 'address' in frappe.db.get_table_columns('Company'): - company_list = frappe.db.sql('''select name, address from `tabCompany` - where address is not null and address != ""''', as_dict=1) - - for company in company_list: - add_list = company.address.split(" ") - if ',' in company.address: - add_list = company.address.rpartition(',') - elif ' ' in company.address: - add_list = company.address.rpartition(' ') - else: - add_list = [company.address, None, company.address] - - doc = frappe.get_doc({ - "doctype":"Address", - "address_line1": add_list[0], - "city": add_list[2], - "links": [{ - "link_doctype": "Company", - "link_name": company.name - }] - }) - doc.save() diff --git a/erpnext/patches/v8_0/create_domain_docs.py b/erpnext/patches/v8_0/create_domain_docs.py deleted file mode 100644 index 3ef4f3c1bb4..00000000000 --- a/erpnext/patches/v8_0/create_domain_docs.py +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe -import erpnext - -def execute(): - """Create domain documents""" - frappe.reload_doc("core", "doctype", "domain") - frappe.reload_doc("core", "doctype", "domain_settings") - frappe.reload_doc("core", "doctype", "has_domain") - frappe.reload_doc("core", "doctype", "role") - - for domain in ("Distribution", "Manufacturing", "Retail", "Services", "Education"): - if not frappe.db.exists({"doctype": "Domain", "domain": domain}): - create_domain(domain) - - # set domain in domain settings based on company domain - - domains = [] - condition = "" - company = erpnext.get_default_company() - if company: - condition = " and name={0}".format(frappe.db.escape(company)) - - domains = frappe.db.sql_list("select distinct domain from `tabCompany` where domain != 'Other' {0}".format(condition)) - - if not domains: - return - - domain_settings = frappe.get_doc("Domain Settings", "Domain Settings") - checked_domains = [row.domain for row in domain_settings.active_domains] - - for domain in domains: - # check and ignore if the domains is already checked in domain settings - if domain in checked_domains: - continue - - if not frappe.db.get_value("Domain", domain): - # user added custom domain in companies domain field - create_domain(domain) - - row = domain_settings.append("active_domains", dict(domain=domain)) - - domain_settings.save(ignore_permissions=True) - -def create_domain(domain): - # create new domain - - doc = frappe.new_doc("Domain") - doc.domain = domain - doc.db_update() \ No newline at end of file diff --git a/erpnext/patches/v8_0/delete_bin_indexes.py b/erpnext/patches/v8_0/delete_bin_indexes.py deleted file mode 100644 index 12cacdb9528..00000000000 --- a/erpnext/patches/v8_0/delete_bin_indexes.py +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt -# -*- coding: utf-8 -*- - -from __future__ import unicode_literals -import frappe - -def execute(): - # delete bin indexes - unwanted_indexes = ["item_code", "warehouse"] - - for k in unwanted_indexes: - try: - frappe.db.sql("drop index {0} on `tabBin`".format(k)) - except: - pass \ No newline at end of file diff --git a/erpnext/patches/v8_0/delete_schools_depricated_doctypes.py b/erpnext/patches/v8_0/delete_schools_depricated_doctypes.py deleted file mode 100644 index 09a78ed3ca6..00000000000 --- a/erpnext/patches/v8_0/delete_schools_depricated_doctypes.py +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2017, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - """ delete doctypes """ - - if frappe.db.exists("DocType", "Grading Structure"): - frappe.delete_doc("DocType", "Grading Structure", force=1) - - if frappe.db.exists("DocType", "Grade Interval"): - frappe.delete_doc("DocType", "Grade Interval", force=1) \ No newline at end of file diff --git a/erpnext/patches/v8_0/disable_instructor_role.py b/erpnext/patches/v8_0/disable_instructor_role.py deleted file mode 100644 index 4ba78d172cb..00000000000 --- a/erpnext/patches/v8_0/disable_instructor_role.py +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - """ - disable the instructor role for companies with domain other than - Education. - """ - - domains = frappe.db.sql_list("select domain from tabCompany") - if "Education" not in domains: - if frappe.db.exists("Role", "Instructor"): - role = frappe.get_doc("Role", "Instructor") - role.disabled = 1 - role.save(ignore_permissions=True) \ No newline at end of file diff --git a/erpnext/patches/v8_0/enable_booking_asset_depreciation_automatically.py b/erpnext/patches/v8_0/enable_booking_asset_depreciation_automatically.py deleted file mode 100644 index 1088d702dd0..00000000000 --- a/erpnext/patches/v8_0/enable_booking_asset_depreciation_automatically.py +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.db.set_value("Accounts Settings", None, - "book_asset_depreciation_entry_automatically", 1) \ No newline at end of file diff --git a/erpnext/patches/v8_0/fix_status_for_invoices_with_negative_outstanding.py b/erpnext/patches/v8_0/fix_status_for_invoices_with_negative_outstanding.py deleted file mode 100644 index 2e7f360c97b..00000000000 --- a/erpnext/patches/v8_0/fix_status_for_invoices_with_negative_outstanding.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - for dt, status in [["Sales Invoice", "Credit Note Issued"], ["Purchase Invoice", "Debit Note Issued"]]: - invoices = frappe.db.sql(""" - select name - from `tab{0}` - where - status = %s - and outstanding_amount < 0 - and docstatus=1 - and is_return=0 - """.format(dt), status) - - for inv in invoices: - return_inv = frappe.db.sql("""select name from `tab{0}` - where is_return=1 and return_against=%s and docstatus=1""".format(dt), inv[0]) - if not return_inv: - frappe.db.sql("update `tab{0}` set status='Paid' where name = %s".format(dt), inv[0]) \ No newline at end of file diff --git a/erpnext/patches/v8_0/make_payments_table_blank_for_non_pos_invoice.py b/erpnext/patches/v8_0/make_payments_table_blank_for_non_pos_invoice.py deleted file mode 100644 index 9750fb72222..00000000000 --- a/erpnext/patches/v8_0/make_payments_table_blank_for_non_pos_invoice.py +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doctype('Sales Invoice') - - frappe.db.sql(""" - delete from - `tabSales Invoice Payment` - where - parent in (select name from `tabSales Invoice` where is_pos = 0) - """) \ No newline at end of file diff --git a/erpnext/patches/v8_0/merge_student_batch_and_student_group.py b/erpnext/patches/v8_0/merge_student_batch_and_student_group.py deleted file mode 100644 index fb9021fd687..00000000000 --- a/erpnext/patches/v8_0/merge_student_batch_and_student_group.py +++ /dev/null @@ -1,73 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe -from frappe.model.utils.rename_field import * -from frappe.model.mapper import get_mapped_doc - - -def execute(): - # for converting student batch into student group - for doctype in ["Student Group", "Student Group Student", 'Program Enrollment', - "Student Group Instructor", "Student Attendance", "Student", "Student Batch Name"]: - # 'Schools' module changed to the 'Education' - # frappe.reload_doc("schools", "doctype", frappe.scrub(doctype)) - - frappe.reload_doc("education", "doctype", frappe.scrub(doctype)) - - if frappe.db.table_exists("Student Batch"): - student_batches = frappe.db.sql('''select name as student_group_name, student_batch_name as batch, - program, academic_year, academic_term from `tabStudent Batch`''', as_dict=1) - - for student_batch in student_batches: - # create student batch name if does not exists !! - if student_batch.get("batch") and not frappe.db.exists("Student Batch Name", student_batch.get("batch")): - frappe.get_doc({ - "doctype": "Student Batch Name", - "batch_name": student_batch.get("batch") - }).insert(ignore_permissions=True) - - student_batch.update({"doctype":"Student Group", "group_based_on": "Batch"}) - doc = frappe.get_doc(student_batch) - - if frappe.db.sql("SHOW COLUMNS FROM `tabStudent Batch Student` LIKE 'active'"): - cond = ", active" - else: - cond = " " - student_list = frappe.db.sql('''select student, student_name {cond} from `tabStudent Batch Student` - where parent=%s'''.format(cond=cond), (doc.student_group_name), as_dict=1) - - if student_list: - for i, student in enumerate(student_list): - student.update({"group_roll_number": i+1}) - doc.extend("students", student_list) - - instructor_list = None - if frappe.db.table_exists("Student Batch Instructor"): - instructor_list = frappe.db.sql('''select instructor, instructor_name from `tabStudent Batch Instructor` - where parent=%s''', (doc.student_group_name), as_dict=1) - if instructor_list: - doc.extend("instructors", instructor_list) - doc.save() - - # delete the student batch and child-table - if frappe.db.table_exists("Student Batch"): - frappe.delete_doc("DocType", "Student Batch", force=1) - if frappe.db.table_exists("Student Batch Student"): - frappe.delete_doc("DocType", "Student Batch Student", force=1) - if frappe.db.table_exists("Student Batch Instructor"): - frappe.delete_doc("DocType", "Student Batch Instructor", force=1) - - # delete the student batch creation tool - if frappe.db.table_exists("Student Batch Creation Tool"): - frappe.delete_doc("DocType", "Student Batch Creation Tool", force=1) - - # delete the student batch creation tool - if frappe.db.table_exists("Attendance Tool Student"): - frappe.delete_doc("DocType", "Attendance Tool Student", force=1) - - # change the student batch to student group in the student attendance - table_columns = frappe.db.get_table_columns("Student Attendance") - if "student_batch" in table_columns: - rename_field("Student Attendance", "student_batch", "student_group") diff --git a/erpnext/patches/v8_0/move_account_head_from_account_to_warehouse_for_inventory.py b/erpnext/patches/v8_0/move_account_head_from_account_to_warehouse_for_inventory.py deleted file mode 100644 index b59d81831f1..00000000000 --- a/erpnext/patches/v8_0/move_account_head_from_account_to_warehouse_for_inventory.py +++ /dev/null @@ -1,15 +0,0 @@ -# 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_doctype("Warehouse") - frappe.db.sql(""" - update - `tabWarehouse` - set - account = (select name from `tabAccount` - where account_type = 'Stock' and - warehouse = `tabWarehouse`.name and is_group = 0 limit 1)""") \ No newline at end of file diff --git a/erpnext/patches/v8_0/move_perpetual_inventory_setting.py b/erpnext/patches/v8_0/move_perpetual_inventory_setting.py deleted file mode 100644 index 78322d4575e..00000000000 --- a/erpnext/patches/v8_0/move_perpetual_inventory_setting.py +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doctype('Company') - enabled = frappe.db.get_single_value("Accounts Settings", "auto_accounting_for_stock") or 0 - for data in frappe.get_all('Company', fields = ["name"]): - doc = frappe.get_doc('Company', data.name) - doc.enable_perpetual_inventory = enabled - doc.db_update() \ No newline at end of file diff --git a/erpnext/patches/v8_0/rename_is_sample_item_to_allow_zero_valuation_rate.py b/erpnext/patches/v8_0/rename_is_sample_item_to_allow_zero_valuation_rate.py deleted file mode 100644 index e517df5fdb9..00000000000 --- a/erpnext/patches/v8_0/rename_is_sample_item_to_allow_zero_valuation_rate.py +++ /dev/null @@ -1,13 +0,0 @@ -from __future__ import unicode_literals -import frappe -from frappe.model.utils.rename_field import rename_field - -def execute(): - - doc_list = ["Purchase Invoice Item", "Stock Entry Detail", "Delivery Note Item", - "Purchase Receipt Item", "Sales Invoice Item"] - - for doctype in doc_list: - frappe.reload_doctype(doctype) - if "is_sample_item" in frappe.db.get_table_columns(doctype): - rename_field(doctype, "is_sample_item", "allow_zero_valuation_rate") \ No newline at end of file diff --git a/erpnext/patches/v8_0/rename_items_in_status_field_of_material_request.py b/erpnext/patches/v8_0/rename_items_in_status_field_of_material_request.py deleted file mode 100644 index 5ad862a4362..00000000000 --- a/erpnext/patches/v8_0/rename_items_in_status_field_of_material_request.py +++ /dev/null @@ -1,25 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.db.sql( - """ - UPDATE `tabMaterial Request` - SET status = CASE - WHEN docstatus = 2 THEN 'Cancelled' - WHEN docstatus = 0 THEN 'Draft' - ELSE CASE - WHEN status = 'Stopped' THEN 'Stopped' - WHEN status != 'Stopped' AND per_ordered = 0 THEN 'Pending' - WHEN per_ordered < 100 AND per_ordered > 0 AND status != 'Stopped' - THEN 'Partially Ordered' - WHEN per_ordered = 100 AND material_request_type = 'Purchase' - AND status != 'Stopped' THEN 'Ordered' - WHEN per_ordered = 100 AND material_request_type = 'Material Transfer' - AND status != 'Stopped' THEN 'Transferred' - WHEN per_ordered = 100 AND material_request_type = 'Material Issue' - AND status != 'Stopped' THEN 'Issued' - END - END - """ - ) \ No newline at end of file diff --git a/erpnext/patches/v8_0/rename_total_margin_to_rate_with_margin.py b/erpnext/patches/v8_0/rename_total_margin_to_rate_with_margin.py deleted file mode 100644 index 40654387961..00000000000 --- a/erpnext/patches/v8_0/rename_total_margin_to_rate_with_margin.py +++ /dev/null @@ -1,24 +0,0 @@ -from __future__ import unicode_literals -import frappe - -from frappe.model.utils.rename_field import rename_field - -def execute(): - """ - Rename Total Margin field to Rate With Margin in - "Sales Order Item", "Sales Invoice Item", "Delivery Note Item", - "Quotation Item" - """ - - for d in ("Sales Order Item", "Sales Invoice Item", - "Delivery Note Item", "Quotation Item"): - frappe.reload_doctype(d) - rename_field_if_exists(d, "total_margin", "rate_with_margin") - - -def rename_field_if_exists(doctype, old_fieldname, new_fieldname): - try: - rename_field(doctype, old_fieldname, new_fieldname) - except Exception as e: - if e.args[0] != 1054: - raise diff --git a/erpnext/patches/v8_0/repost_reserved_qty_for_multiple_sales_uom.py b/erpnext/patches/v8_0/repost_reserved_qty_for_multiple_sales_uom.py deleted file mode 100644 index 3030b8e2f37..00000000000 --- a/erpnext/patches/v8_0/repost_reserved_qty_for_multiple_sales_uom.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe -from erpnext.stock.stock_balance import update_bin_qty, get_reserved_qty - -def execute(): - for doctype in ("Sales Order Item", "Bin"): - frappe.reload_doctype(doctype) - - repost_for = frappe.db.sql("""select distinct item_code, warehouse - from `tabSales Order Item` where docstatus=1 and uom != stock_uom and - exists(select name from tabItem where name=`tabSales Order Item`.item_code and ifnull(is_stock_item, 0)=1)""") - - for item_code, warehouse in repost_for: - update_bin_qty(item_code, warehouse, { - "reserved_qty": get_reserved_qty(item_code, warehouse) - }) \ No newline at end of file diff --git a/erpnext/patches/v8_0/revert_manufacturers_table_from_item.py b/erpnext/patches/v8_0/revert_manufacturers_table_from_item.py deleted file mode 100644 index 60cbb33b80b..00000000000 --- a/erpnext/patches/v8_0/revert_manufacturers_table_from_item.py +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - if frappe.db.exists("DocType", "Item Manufacturer"): - frappe.reload_doctype("Item") - item_manufacturers = frappe.db.sql(""" - select parent, manufacturer, manufacturer_part_no - from `tabItem Manufacturer` - """, as_dict=1) - - for im in item_manufacturers: - frappe.db.sql(""" - update tabItem - set manufacturer=%s, manufacturer_part_no=%s - where name=%s - """, (im.manufacturer, im.manufacturer_part_no, im.parent)) - - frappe.delete_doc("DocType", "Item Manufacturer") \ No newline at end of file diff --git a/erpnext/patches/v8_0/save_system_settings.py b/erpnext/patches/v8_0/save_system_settings.py deleted file mode 100644 index d479ece8a69..00000000000 --- a/erpnext/patches/v8_0/save_system_settings.py +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe -from frappe.utils import cint - -def execute(): - """ - save system settings document - """ - - frappe.reload_doc("core", "doctype", "system_settings") - doc = frappe.get_doc("System Settings") - doc.flags.ignore_mandatory = True - - if cint(doc.currency_precision) == 0: - doc.currency_precision = '' - - doc.save(ignore_permissions=True) diff --git a/erpnext/patches/v8_0/set_null_to_serial_nos_for_disabled_sales_invoices.py b/erpnext/patches/v8_0/set_null_to_serial_nos_for_disabled_sales_invoices.py deleted file mode 100644 index 197d6ded61a..00000000000 --- a/erpnext/patches/v8_0/set_null_to_serial_nos_for_disabled_sales_invoices.py +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe -from erpnext.stock.stock_balance import update_bin_qty, get_reserved_qty - -def execute(): - frappe.db.sql(""" - update - `tabSales Invoice Item` - set serial_no = NULL - where - parent in (select name from `tabSales Invoice` where update_stock = 0 and docstatus = 1)""") \ No newline at end of file diff --git a/erpnext/patches/v8_0/set_project_copied_from.py b/erpnext/patches/v8_0/set_project_copied_from.py deleted file mode 100644 index d4287978cf8..00000000000 --- a/erpnext/patches/v8_0/set_project_copied_from.py +++ /dev/null @@ -1,11 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doctype("Project") - - frappe.db.sql(''' - UPDATE `tabProject` - SET copied_from=name - WHERE copied_from is NULL - ''') \ No newline at end of file diff --git a/erpnext/patches/v8_0/set_sales_invoice_serial_number_from_delivery_note.py b/erpnext/patches/v8_0/set_sales_invoice_serial_number_from_delivery_note.py deleted file mode 100644 index 8a4ef4086b6..00000000000 --- a/erpnext/patches/v8_0/set_sales_invoice_serial_number_from_delivery_note.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe -from erpnext.stock.stock_balance import update_bin_qty, get_reserved_qty - -def execute(): - """ Set the Serial Numbers in Sales Invoice Item from Delivery Note Item """ - - frappe.reload_doc("stock", "doctype", "serial_no") - - frappe.db.sql(""" update `tabSales Invoice Item` sii inner join - `tabDelivery Note Item` dni on sii.dn_detail=dni.name and sii.qty=dni.qty - set sii.serial_no=dni.serial_no where sii.parent IN (select si.name - from `tabSales Invoice` si where si.update_stock=0 and si.docstatus=1)""") - - items = frappe.db.sql(""" select sii.parent, sii.serial_no from `tabSales Invoice Item` sii - left join `tabSales Invoice` si on sii.parent=si.name - where si.docstatus=1 and si.update_stock=0""", as_dict=True) - - for item in items: - sales_invoice = item.get("parent", None) - serial_nos = item.get("serial_no", "") - - if not sales_invoice or not serial_nos: - continue - - serial_nos = ["{}".format(frappe.db.escape(no)) for no in serial_nos.split("\n")] - - frappe.db.sql(""" - UPDATE - `tabSerial No` - SET - sales_invoice={sales_invoice} - WHERE - name in ({serial_nos}) - """.format( - sales_invoice=frappe.db.escape(sales_invoice), - serial_nos=",".join(serial_nos) - ) - ) \ No newline at end of file diff --git a/erpnext/patches/v8_0/update_customer_pos_id.py b/erpnext/patches/v8_0/update_customer_pos_id.py deleted file mode 100644 index a772ae90c5d..00000000000 --- a/erpnext/patches/v8_0/update_customer_pos_id.py +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doctype("Customer") - frappe.db.sql(""" update `tabCustomer` set customer_pos_id = name """) \ No newline at end of file diff --git a/erpnext/patches/v8_0/update_production_orders.py b/erpnext/patches/v8_0/update_production_orders.py deleted file mode 100644 index 8e993cc1020..00000000000 --- a/erpnext/patches/v8_0/update_production_orders.py +++ /dev/null @@ -1,49 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - # reload schema - for doctype in ("Work Order", "Work Order Item", "Work Order Operation", - "BOM Item", "BOM Explosion Item", "BOM"): - frappe.reload_doctype(doctype) - - frappe.reload_doc("stock", "doctype", "item") - frappe.reload_doc("stock", "doctype", "item_default") - - # fetch all draft and submitted work orders - fields = ["name"] - if "source_warehouse" in frappe.db.get_table_columns("Work Order"): - fields.append("source_warehouse") - - wo_orders = frappe.get_all("Work Order", filters={"docstatus": ["!=", 2]}, fields=fields) - - count = 0 - for p in wo_orders: - wo_order = frappe.get_doc("Work Order", p.name) - count += 1 - - # set required items table - wo_order.set_required_items() - - for item in wo_order.get("required_items"): - # set source warehouse based on parent - if not item.source_warehouse and "source_warehouse" in fields: - item.source_warehouse = wo_order.get("source_warehouse") - item.db_update() - - if wo_order.docstatus == 1: - # update transferred qty based on Stock Entry, it also updates db - wo_order.update_transaferred_qty_for_required_items() - - # Set status where it was 'Unstopped', as it is deprecated - if wo_order.status == "Unstopped": - status = wo_order.get_status() - wo_order.db_set("status", status) - elif wo_order.status == "Stopped": - wo_order.update_reserved_qty_for_production() - - if count % 200 == 0: - frappe.db.commit() \ No newline at end of file diff --git a/erpnext/patches/v8_0/update_sales_cost_in_project.py b/erpnext/patches/v8_0/update_sales_cost_in_project.py deleted file mode 100644 index 1a29fc4db4f..00000000000 --- a/erpnext/patches/v8_0/update_sales_cost_in_project.py +++ /dev/null @@ -1,11 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doc("projects", "doctype", "project") - - frappe.db.sql(""" - update `tabProject` p - set total_sales_amount = ifnull((select sum(base_grand_total) - from `tabSales Order` where project=p.name and docstatus=1), 0) - """) \ No newline at end of file diff --git a/erpnext/patches/v8_0/update_status_as_paid_for_completed_expense_claim.py b/erpnext/patches/v8_0/update_status_as_paid_for_completed_expense_claim.py deleted file mode 100644 index 19d27b206b1..00000000000 --- a/erpnext/patches/v8_0/update_status_as_paid_for_completed_expense_claim.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - """ set status as Paid in Expense Claim if total_sactioned_amount - and total_amount_reimbursed is equal """ - - frappe.reload_doctype('Expense Claim') - - frappe.db.sql(""" - update - `tabExpense Claim` - set status = 'Paid' - where - total_sanctioned_amount = total_amount_reimbursed - """) diff --git a/erpnext/patches/v8_0/update_stock_qty_value_in_bom_item.py b/erpnext/patches/v8_0/update_stock_qty_value_in_bom_item.py deleted file mode 100644 index 1f937bb8af8..00000000000 --- a/erpnext/patches/v8_0/update_stock_qty_value_in_bom_item.py +++ /dev/null @@ -1,14 +0,0 @@ -# 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('manufacturing', 'doctype', 'bom_item') - frappe.reload_doc('manufacturing', 'doctype', 'bom_explosion_item') - frappe.reload_doc('manufacturing', 'doctype', 'bom_scrap_item') - frappe.db.sql("update `tabBOM Item` set stock_qty = qty, uom = stock_uom, conversion_factor = 1") - frappe.db.sql("update `tabBOM Explosion Item` set stock_qty = qty") - if "qty" in frappe.db.get_table_columns("BOM Scrap Item"): - frappe.db.sql("update `tabBOM Scrap Item` set stock_qty = qty") \ No newline at end of file diff --git a/erpnext/patches/v8_0/update_stock_qty_value_in_purchase_invoice.py b/erpnext/patches/v8_0/update_stock_qty_value_in_purchase_invoice.py deleted file mode 100644 index be5cf3aed77..00000000000 --- a/erpnext/patches/v8_0/update_stock_qty_value_in_purchase_invoice.py +++ /dev/null @@ -1,9 +0,0 @@ -# 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('accounts', 'doctype', 'purchase_invoice_item') - frappe.db.sql("update `tabPurchase Invoice Item` set stock_qty = qty, stock_uom = uom") \ No newline at end of file diff --git a/erpnext/patches/v8_0/update_student_groups_from_student_batches.py b/erpnext/patches/v8_0/update_student_groups_from_student_batches.py deleted file mode 100644 index ae24fe4a14e..00000000000 --- a/erpnext/patches/v8_0/update_student_groups_from_student_batches.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe -from frappe.model.utils.rename_field import * -from frappe.model.mapper import get_mapped_doc - - -def execute(): - if frappe.db.table_exists("Student Batch"): - student_batches = frappe.db.sql('''select name from `tabStudent Batch`''', as_dict=1) - - for student_batch in student_batches: - if frappe.db.exists("Student Group", student_batch.get("name")): - student_group = frappe.get_doc("Student Group", student_batch.get("name")) - - if frappe.db.table_exists("Student Batch Student"): - current_student_list = frappe.db.sql_list('''select student from `tabStudent Group Student` - where parent=%s''', (student_group.name)) - batch_student_list = frappe.db.sql_list('''select student from `tabStudent Batch Student` - where parent=%s''', (student_group.name)) - - student_list = list(set(batch_student_list)-set(current_student_list)) - if student_list: - student_group.extend("students", [{"student":d} for d in student_list]) - - if frappe.db.table_exists("Student Batch Instructor"): - current_instructor_list = frappe.db.sql_list('''select instructor from `tabStudent Group Instructor` - where parent=%s''', (student_group.name)) - batch_instructor_list = frappe.db.sql_list('''select instructor from `tabStudent Batch Instructor` - where parent=%s''', (student_group.name)) - - instructor_list = list(set(batch_instructor_list)-set(current_instructor_list)) - if instructor_list: - student_group.extend("instructors", [{"instructor":d} for d in instructor_list]) - - student_group.save() diff --git a/erpnext/patches/v8_0/update_supplier_address_in_stock_entry.py b/erpnext/patches/v8_0/update_supplier_address_in_stock_entry.py deleted file mode 100644 index a2173048fd4..00000000000 --- a/erpnext/patches/v8_0/update_supplier_address_in_stock_entry.py +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - # copy supplier_address to address_display, and set supplier_address to blank - - stock_entries = frappe.db.sql(""" select name, purchase_order, supplier_address from `tabStock Entry` - where ifnull(supplier_address, '') <> ''""", as_dict=True) - - frappe.reload_doc('stock', 'doctype', 'stock_entry') - - for stock_entry in stock_entries: - # move supplier address to address_display, and fetch the supplier address from purchase order - - se = frappe.get_doc("Stock Entry", stock_entry.get("name")) - se.address_display = stock_entry.get("supplier_address") - se.supplier_address = frappe.db.get_value("Purchase Order", stock_entry.get("purchase_order"),"supplier_address") or None - - se.db_update() diff --git a/erpnext/patches/v8_1/__init__.py b/erpnext/patches/v8_1/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/erpnext/patches/v8_1/add_hsn_sac_codes.py b/erpnext/patches/v8_1/add_hsn_sac_codes.py deleted file mode 100644 index 0fce96a8d4e..00000000000 --- a/erpnext/patches/v8_1/add_hsn_sac_codes.py +++ /dev/null @@ -1,11 +0,0 @@ -from __future__ import unicode_literals -import frappe -from erpnext.regional.india.setup import setup - -def execute(): - company = frappe.get_all('Company', filters = {'country': 'India'}) - if not company: - return - - # call setup for india - setup(patch=True) \ No newline at end of file diff --git a/erpnext/patches/v8_1/add_indexes_in_transaction_doctypes.py b/erpnext/patches/v8_1/add_indexes_in_transaction_doctypes.py deleted file mode 100644 index 46316026068..00000000000 --- a/erpnext/patches/v8_1/add_indexes_in_transaction_doctypes.py +++ /dev/null @@ -1,10 +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 - -def execute(): - for dt in ("Sales Order Item", "Purchase Order Item", - "Material Request Item", "Work Order Item", "Packed Item"): - frappe.get_doc("DocType", dt).run_module_method("on_doctype_update") \ No newline at end of file diff --git a/erpnext/patches/v8_1/allow_invoice_copy_to_edit_after_submit.py b/erpnext/patches/v8_1/allow_invoice_copy_to_edit_after_submit.py deleted file mode 100644 index 4c606af4243..00000000000 --- a/erpnext/patches/v8_1/allow_invoice_copy_to_edit_after_submit.py +++ /dev/null @@ -1,13 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - inv_copy_options = "ORIGINAL FOR RECIPIENT\nDUPLICATE FOR TRANSPORTER\nDUPLICATE FOR SUPPLIER\nTRIPLICATE FOR SUPPLIER" - - frappe.db.sql("""update `tabCustom Field` set allow_on_submit=1, options=%s - where fieldname='invoice_copy' and dt = 'Sales Invoice' - """, inv_copy_options) - - frappe.db.sql("""update `tabCustom Field` set read_only=1 - where fieldname='gst_state_number' and dt = 'Address' - """) diff --git a/erpnext/patches/v8_1/delete_deprecated_reports.py b/erpnext/patches/v8_1/delete_deprecated_reports.py deleted file mode 100644 index 3e0fdee7192..00000000000 --- a/erpnext/patches/v8_1/delete_deprecated_reports.py +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - """ delete deprecated reports """ - - reports = [ - "Monthly Salary Register", "Customer Addresses And Contacts", - "Supplier Addresses And Contacts" - ] - - for report in reports: - if frappe.db.exists("Report", report): - check_and_update_auto_email_report(report) - frappe.db.commit() - - frappe.delete_doc("Report", report, ignore_permissions=True) - -def check_and_update_auto_email_report(report): - """ delete or update auto email report for deprecated report """ - - auto_email_report = frappe.db.get_value("Auto Email Report", {"report": report}) - if not auto_email_report: - return - - if report == "Monthly Salary Register": - frappe.delete_doc("Auto Email Report", auto_email_report) - - elif report in ["Customer Addresses And Contacts", "Supplier Addresses And Contacts"]: - frappe.db.set_value("Auto Email Report", auto_email_report, "report", report) \ No newline at end of file diff --git a/erpnext/patches/v8_1/gst_fixes.py b/erpnext/patches/v8_1/gst_fixes.py deleted file mode 100644 index 34255eb0a42..00000000000 --- a/erpnext/patches/v8_1/gst_fixes.py +++ /dev/null @@ -1,62 +0,0 @@ -from __future__ import unicode_literals -import frappe -from frappe.custom.doctype.custom_field.custom_field import create_custom_field -from erpnext.regional.address_template.setup import set_up_address_templates - - -def execute(): - company = frappe.get_all('Company', filters = {'country': 'India'}) - if not company: - return - - update_existing_custom_fields() - add_custom_fields() - set_up_address_templates(default_country='India') - frappe.reload_doc("regional", "print_format", "gst_tax_invoice") - - -def update_existing_custom_fields(): - frappe.db.sql("""update `tabCustom Field` set label = 'HSN/SAC' - where fieldname='gst_hsn_code' and label='GST HSN Code' - """) - - frappe.db.sql("""update `tabCustom Field` set print_hide = 1 - where fieldname in ('customer_gstin', 'supplier_gstin', 'company_gstin') - """) - - frappe.db.sql("""update `tabCustom Field` set insert_after = 'address_display' - where fieldname in ('customer_gstin', 'supplier_gstin') - """) - - frappe.db.sql("""update `tabCustom Field` set insert_after = 'company_address_display' - where fieldname = 'company_gstin' - """) - - frappe.db.sql("""update `tabCustom Field` set insert_after = 'description' - where fieldname='gst_hsn_code' and dt in ('Sales Invoice Item', 'Purchase Invoice Item') - """) - - -def add_custom_fields(): - hsn_sac_field = dict(fieldname='gst_hsn_code', label='HSN/SAC', - fieldtype='Data', options='item_code.gst_hsn_code', insert_after='description') - - custom_fields = { - 'Address': [ - dict(fieldname='gst_state_number', label='GST State Number', - fieldtype='Int', insert_after='gst_state'), - ], - 'Sales Invoice': [ - dict(fieldname='invoice_copy', label='Invoice Copy', - fieldtype='Select', insert_after='project', print_hide=1, allow_on_submit=1, - options='ORIGINAL FOR RECIPIENT\nDUPLICATE FOR TRANSPORTER\nTRIPLICATE FOR SUPPLIER'), - ], - 'Sales Order Item': [hsn_sac_field], - 'Delivery Note Item': [hsn_sac_field], - 'Purchase Order Item': [hsn_sac_field], - 'Purchase Receipt Item': [hsn_sac_field] - } - - for doctype, fields in custom_fields.items(): - for df in fields: - create_custom_field(doctype, df) diff --git a/erpnext/patches/v8_1/remove_sales_invoice_from_returned_serial_no.py b/erpnext/patches/v8_1/remove_sales_invoice_from_returned_serial_no.py deleted file mode 100644 index 3962f8f1f21..00000000000 --- a/erpnext/patches/v8_1/remove_sales_invoice_from_returned_serial_no.py +++ /dev/null @@ -1,18 +0,0 @@ -# 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_doctype("Serial No") - - frappe.db.sql(""" - update - `tabSerial No` - set - sales_invoice = NULL - where - sales_invoice in (select return_against from - `tabSales Invoice` where docstatus =1 and is_return=1) - and sales_invoice is not null and sales_invoice !='' """) \ No newline at end of file diff --git a/erpnext/patches/v8_1/removed_report_support_hours.py b/erpnext/patches/v8_1/removed_report_support_hours.py deleted file mode 100644 index 0936b2231bb..00000000000 --- a/erpnext/patches/v8_1/removed_report_support_hours.py +++ /dev/null @@ -1,14 +0,0 @@ -# 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.db.sql(""" update `tabAuto Email Report` set report = %s - where name = %s""", ('Support Hour Distribution', 'Support Hours')) - - frappe.db.sql(""" update `tabCustom Role` set report = %s - where report = %s""", ('Support Hour Distribution', 'Support Hours')) - - frappe.delete_doc('Report', 'Support Hours') \ No newline at end of file diff --git a/erpnext/patches/v8_1/set_delivery_date_in_so_item.py b/erpnext/patches/v8_1/set_delivery_date_in_so_item.py deleted file mode 100644 index af2d28b857f..00000000000 --- a/erpnext/patches/v8_1/set_delivery_date_in_so_item.py +++ /dev/null @@ -1,22 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doctype("Sales Order") - frappe.reload_doctype("Sales Order Item") - - if "final_delivery_date" in frappe.db.get_table_columns("Sales Order"): - frappe.db.sql(""" - update `tabSales Order` - set delivery_date = final_delivery_date - where (delivery_date is null or delivery_date = '0000-00-00') - and order_type = 'Sales'""") - - frappe.db.sql(""" - update `tabSales Order` so, `tabSales Order Item` so_item - set so_item.delivery_date = so.delivery_date - where so.name = so_item.parent - and so.order_type = 'Sales' - and (so_item.delivery_date is null or so_item.delivery_date = '0000-00-00') - and (so.delivery_date is not null and so.delivery_date != '0000-00-00') - """) \ No newline at end of file diff --git a/erpnext/patches/v8_1/update_expense_claim_status.py b/erpnext/patches/v8_1/update_expense_claim_status.py deleted file mode 100644 index 4c1b85a13f0..00000000000 --- a/erpnext/patches/v8_1/update_expense_claim_status.py +++ /dev/null @@ -1,23 +0,0 @@ -# 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_doctype('Expense Claim') - - for data in frappe.db.sql(""" select name from `tabExpense Claim` - where (docstatus=1 and total_sanctioned_amount=0 and status = 'Paid') or - (docstatus = 1 and approval_status = 'Rejected' and total_sanctioned_amount > 0)""", as_dict=1): - doc = frappe.get_doc('Expense Claim', data.name) - if doc.approval_status == 'Rejected': - for d in doc.expenses: - d.db_set("sanctioned_amount", 0, update_modified = False) - doc.db_set("total_sanctioned_amount", 0, update_modified = False) - - frappe.db.sql(""" delete from `tabGL Entry` where voucher_type = 'Expense Claim' - and voucher_no = %s""", (doc.name)) - - doc.set_status() - doc.db_set("status", doc.status, update_modified = False) \ No newline at end of file diff --git a/erpnext/patches/v8_1/update_gst_state.py b/erpnext/patches/v8_1/update_gst_state.py deleted file mode 100644 index 7aaf2d5ff31..00000000000 --- a/erpnext/patches/v8_1/update_gst_state.py +++ /dev/null @@ -1,15 +0,0 @@ -from __future__ import unicode_literals -import frappe -from erpnext.regional.india import states - -def execute(): - company = frappe.get_all('Company', filters = {'country': 'India'}) - if not company: - return - - if not frappe.db.get_value("Custom Field", filters={'fieldname':'gst_state'}): - return - - frappe.db.sql("update `tabCustom Field` set options=%s where fieldname='gst_state'", '\n'.join(states)) - frappe.db.sql("update `tabAddress` set gst_state='Chhattisgarh' where gst_state='Chattisgarh'") - frappe.db.sql("update `tabAddress` set gst_state_number='05' where gst_state='Uttarakhand'") diff --git a/erpnext/patches/v8_10/__init__.py b/erpnext/patches/v8_10/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/erpnext/patches/v8_10/change_default_customer_credit_days.py b/erpnext/patches/v8_10/change_default_customer_credit_days.py deleted file mode 100644 index 992be17da04..00000000000 --- a/erpnext/patches/v8_10/change_default_customer_credit_days.py +++ /dev/null @@ -1,89 +0,0 @@ -from __future__ import unicode_literals -import frappe - - -def execute(): - frappe.reload_doc("selling", "doctype", "customer") - frappe.reload_doc("buying", "doctype", "supplier") - frappe.reload_doc("setup", "doctype", "supplier_type") - frappe.reload_doc("accounts", "doctype", "payment_term") - frappe.reload_doc("accounts", "doctype", "payment_terms_template_detail") - frappe.reload_doc("accounts", "doctype", "payment_terms_template") - - payment_terms = [] - records = [] - for doctype in ("Customer", "Supplier", "Supplier Type"): - credit_days = frappe.db.sql(""" - SELECT DISTINCT `credit_days`, `credit_days_based_on`, `name` - from `tab{0}` - where - ((credit_days_based_on='Fixed Days' or credit_days_based_on is null) - and credit_days is not null) - or credit_days_based_on='Last Day of the Next Month' - """.format(doctype)) - - credit_records = ((record[0], record[1], record[2]) for record in credit_days) - for days, based_on, party_name in credit_records: - if based_on == "Fixed Days": - pyt_template_name = 'Default Payment Term - N{0}'.format(days) - else: - pyt_template_name = 'Default Payment Term - EO2M' - - if not frappe.db.exists("Payment Terms Template", pyt_template_name): - payment_term = make_payment_term(days, based_on) - template = make_template(payment_term) - else: - template = frappe.get_doc("Payment Terms Template", pyt_template_name) - - payment_terms.append('WHEN `name`={0} THEN {1}'.format(frappe.db.escape(party_name), template.template_name)) - records.append(frappe.db.escape(party_name)) - - begin_query_str = "UPDATE `tab{0}` SET `payment_terms` = CASE ".format(doctype) - value_query_str = " ".join(payment_terms) - cond_query_str = " ELSE `payment_terms` END WHERE " - - if records: - frappe.db.sql( - begin_query_str + value_query_str + cond_query_str + '`name` IN %s', - (records,) - ) - - -def make_template(payment_term): - doc = frappe.new_doc('Payment Terms Template Detail') - doc.payment_term = payment_term.payment_term_name - doc.due_date_based_on = payment_term.due_date_based_on - doc.invoice_portion = payment_term.invoice_portion - doc.description = payment_term.description - doc.credit_days = payment_term.credit_days - doc.credit_months = payment_term.credit_months - - template = frappe.new_doc('Payment Terms Template') - template.template_name = 'Default Payment Term - {0}'.format(payment_term.payment_term_name) - template.append('terms', doc) - template.save() - - return template - - -def make_payment_term(days, based_on): - based_on_map = { - 'Fixed Days': 'Day(s) after invoice date', - 'Last Day of the Next Month': 'Month(s) after the end of the invoice month' - } - - doc = frappe.new_doc('Payment Term') - doc.due_date_based_on = based_on_map.get(based_on) - doc.invoice_portion = 100 - - if based_on == 'Fixed Days': - doc.credit_days = days - doc.description = 'Net payable within {0} days'.format(days) - doc.payment_term_name = 'N{0}'.format(days) - else: - doc.credit_months = 1 - doc.description = 'Net payable by the end of next month' - doc.payment_term_name = 'EO2M' - - doc.save() - return doc diff --git a/erpnext/patches/v8_3/__init__.py b/erpnext/patches/v8_3/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/erpnext/patches/v8_3/set_restrict_to_domain_for_module_def.py b/erpnext/patches/v8_3/set_restrict_to_domain_for_module_def.py deleted file mode 100644 index 6c4c6d5bd8d..00000000000 --- a/erpnext/patches/v8_3/set_restrict_to_domain_for_module_def.py +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - """ set the restrict to domain in module def """ - pass \ No newline at end of file diff --git a/erpnext/patches/v8_3/update_company_total_sales.py b/erpnext/patches/v8_3/update_company_total_sales.py deleted file mode 100644 index 78efecb3872..00000000000 --- a/erpnext/patches/v8_3/update_company_total_sales.py +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe -from erpnext.setup.doctype.company.company import update_company_current_month_sales, update_company_monthly_sales - -def execute(): - '''Update company monthly sales history based on sales invoices''' - frappe.reload_doctype("Company") - companies = [d['name'] for d in frappe.get_list("Company")] - - for company in companies: - update_company_current_month_sales(company) - update_company_monthly_sales(company) diff --git a/erpnext/patches/v8_4/__init__.py b/erpnext/patches/v8_4/__init__.py deleted file mode 100644 index baffc488252..00000000000 --- a/erpnext/patches/v8_4/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from __future__ import unicode_literals diff --git a/erpnext/patches/v8_4/make_scorecard_records.py b/erpnext/patches/v8_4/make_scorecard_records.py deleted file mode 100644 index 73afa277b4b..00000000000 --- a/erpnext/patches/v8_4/make_scorecard_records.py +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -from erpnext.buying.doctype.supplier_scorecard.supplier_scorecard import make_default_records -def execute(): - frappe.reload_doc('buying', 'doctype', 'supplier_scorecard_variable') - frappe.reload_doc('buying', 'doctype', 'supplier_scorecard_standing') - make_default_records() \ No newline at end of file diff --git a/erpnext/patches/v8_5/__init__.py b/erpnext/patches/v8_5/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/erpnext/patches/v8_5/fix_tax_breakup_for_non_invoice_docs.py b/erpnext/patches/v8_5/fix_tax_breakup_for_non_invoice_docs.py deleted file mode 100644 index 82beba37702..00000000000 --- a/erpnext/patches/v8_5/fix_tax_breakup_for_non_invoice_docs.py +++ /dev/null @@ -1,48 +0,0 @@ -from __future__ import unicode_literals -import frappe -from erpnext.regional.india.setup import make_custom_fields -from erpnext.controllers.taxes_and_totals import get_itemised_tax_breakup_html - -def execute(): - companies = [d.name for d in frappe.get_all('Company', filters = {'country': 'India'})] - if not companies: - return - - make_custom_fields() - - # update invoice copy value - values = ["Original for Recipient", "Duplicate for Transporter", - "Duplicate for Supplier", "Triplicate for Supplier"] - for d in values: - frappe.db.sql("update `tabSales Invoice` set invoice_copy=%s where invoice_copy=%s", (d, d)) - - # update tax breakup in transactions made after 1st July 2017 - doctypes = ["Quotation", "Sales Order", "Delivery Note", "Sales Invoice", - "Supplier Quotation", "Purchase Order", "Purchase Receipt", "Purchase Invoice"] - - for doctype in doctypes: - frappe.reload_doctype(doctype) - - date_field = "posting_date" - if doctype in ["Quotation", "Sales Order", "Supplier Quotation", "Purchase Order"]: - date_field = "transaction_date" - - records = [d.name for d in frappe.get_all(doctype, filters={ - "docstatus": ["!=", 2], - date_field: [">=", "2017-07-01"], - "company": ["in", companies], - "total_taxes_and_charges": [">", 0], - "other_charges_calculation": "" - })] - if records: - frappe.db.sql(""" - update `tab%s Item` dt_item - set gst_hsn_code = (select gst_hsn_code from tabItem where name=dt_item.item_code) - where parent in (%s) - and (gst_hsn_code is null or gst_hsn_code = '') - """ % (doctype, ', '.join(['%s']*len(records))), tuple(records)) - - for record in records: - doc = frappe.get_doc(doctype, record) - html = get_itemised_tax_breakup_html(doc) - doc.db_set("other_charges_calculation", html, update_modified=False) \ No newline at end of file diff --git a/erpnext/patches/v8_5/remove_project_type_property_setter.py b/erpnext/patches/v8_5/remove_project_type_property_setter.py deleted file mode 100644 index 70a08f53776..00000000000 --- a/erpnext/patches/v8_5/remove_project_type_property_setter.py +++ /dev/null @@ -1,18 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - ps = frappe.db.get_value('Property Setter', dict(doc_type='Project', field_name='project_type', - property='options')) - if ps: - frappe.delete_doc('Property Setter', ps) - - project_types = frappe.db.sql_list('select distinct project_type from tabProject') - - for project_type in project_types: - if project_type and not frappe.db.exists("Project Type", project_type): - p_type = frappe.get_doc({ - "doctype": "Project Type", - "project_type": project_type - }) - p_type.insert() \ No newline at end of file diff --git a/erpnext/patches/v8_5/remove_quotations_route_in_sidebar.py b/erpnext/patches/v8_5/remove_quotations_route_in_sidebar.py deleted file mode 100644 index 2d7df4a179d..00000000000 --- a/erpnext/patches/v8_5/remove_quotations_route_in_sidebar.py +++ /dev/null @@ -1,16 +0,0 @@ -# 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_doctype("Portal Settings") - - frappe.db.sql(""" - delete from - `tabPortal Menu Item` - where - (route = '/quotations' and title = 'Supplier Quotation') - or (route = '/quotation' and title = 'Quotations') - """) \ No newline at end of file diff --git a/erpnext/patches/v8_5/set_default_mode_of_payment.py b/erpnext/patches/v8_5/set_default_mode_of_payment.py deleted file mode 100644 index 34ecbb0a3c3..00000000000 --- a/erpnext/patches/v8_5/set_default_mode_of_payment.py +++ /dev/null @@ -1,17 +0,0 @@ -# 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_doctype("POS Profile") - frappe.reload_doctype("Sales Invoice Payment") - - frappe.db.sql(""" - update - `tabSales Invoice Payment` - set `tabSales Invoice Payment`.default = 1 - where - `tabSales Invoice Payment`.parenttype = 'POS Profile' - and `tabSales Invoice Payment`.idx=1""") \ No newline at end of file diff --git a/erpnext/patches/v8_5/update_customer_group_in_POS_profile.py b/erpnext/patches/v8_5/update_customer_group_in_POS_profile.py deleted file mode 100644 index 2661914401b..00000000000 --- a/erpnext/patches/v8_5/update_customer_group_in_POS_profile.py +++ /dev/null @@ -1,9 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doctype('POS Profile') - customer_group = frappe.db.get_single_value('Selling Settings', 'customer_group') - if customer_group: - frappe.db.sql(""" update `tabPOS Profile` - set customer_group = %s where customer_group is null """, (customer_group)) \ No newline at end of file diff --git a/erpnext/patches/v8_5/update_existing_data_in_project_type.py b/erpnext/patches/v8_5/update_existing_data_in_project_type.py deleted file mode 100644 index 497da0602e3..00000000000 --- a/erpnext/patches/v8_5/update_existing_data_in_project_type.py +++ /dev/null @@ -1,19 +0,0 @@ -# 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("projects", "doctype", "project_type") - frappe.reload_doc("projects", "doctype", "project") - - project_types = ["Internal", "External", "Other"] - - for project_type in project_types: - if not frappe.db.exists("Project Type", project_type): - p_type = frappe.get_doc({ - "doctype": "Project Type", - "project_type": project_type - }) - p_type.insert() \ No newline at end of file diff --git a/erpnext/patches/v8_6/__init__.py b/erpnext/patches/v8_6/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/erpnext/patches/v8_6/point_sms_doctype_module_to_frappe_core.py b/erpnext/patches/v8_6/point_sms_doctype_module_to_frappe_core.py deleted file mode 100644 index 014a74abe36..00000000000 --- a/erpnext/patches/v8_6/point_sms_doctype_module_to_frappe_core.py +++ /dev/null @@ -1,9 +0,0 @@ -# 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.db.sql('''UPDATE `tabDocType` SET module="Core" - WHERE name IN ("SMS Parameter", "SMS Settings");''') \ No newline at end of file diff --git a/erpnext/patches/v8_6/rename_bom_update_tool.py b/erpnext/patches/v8_6/rename_bom_update_tool.py deleted file mode 100644 index ef5f335e45f..00000000000 --- a/erpnext/patches/v8_6/rename_bom_update_tool.py +++ /dev/null @@ -1,9 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.delete_doc_if_exists("DocType", "BOM Replace Tool") - - frappe.reload_doctype("BOM") - frappe.db.sql("update tabBOM set conversion_rate=1 where conversion_rate is null or conversion_rate=0") - frappe.db.sql("update tabBOM set set_rate_of_sub_assembly_item_based_on_bom=1") \ No newline at end of file diff --git a/erpnext/patches/v8_6/set_write_permission_for_quotation_for_sales_manager.py b/erpnext/patches/v8_6/set_write_permission_for_quotation_for_sales_manager.py deleted file mode 100644 index db4f94748e1..00000000000 --- a/erpnext/patches/v8_6/set_write_permission_for_quotation_for_sales_manager.py +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - # Set write permission to permlevel 1 for sales manager role in Quotation doctype - frappe.db.sql(""" update `tabCustom DocPerm` set `tabCustom DocPerm`.write = 1 - where `tabCustom DocPerm`.parent = 'Quotation' and `tabCustom DocPerm`.role = 'Sales Manager' - and `tabCustom DocPerm`.permlevel = 1 """) \ No newline at end of file diff --git a/erpnext/patches/v8_6/update_timesheet_company_from_PO.py b/erpnext/patches/v8_6/update_timesheet_company_from_PO.py deleted file mode 100644 index 2d46bee7caa..00000000000 --- a/erpnext/patches/v8_6/update_timesheet_company_from_PO.py +++ /dev/null @@ -1,15 +0,0 @@ -# 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_doctype('Timesheet') - company = frappe.get_all('Company') - - #Check more than one company exists - if len(company) > 1: - frappe.db.sql(""" update `tabTimesheet` set `tabTimesheet`.company = - (select company from `tabWork Order` where name = `tabTimesheet`.work_order) - where workn_order is not null and work_order !=''""") \ No newline at end of file diff --git a/erpnext/patches/v8_7/__init__.py b/erpnext/patches/v8_7/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/erpnext/patches/v8_7/fix_purchase_receipt_status.py b/erpnext/patches/v8_7/fix_purchase_receipt_status.py deleted file mode 100644 index 99ecb442149..00000000000 --- a/erpnext/patches/v8_7/fix_purchase_receipt_status.py +++ /dev/null @@ -1,13 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - # there is no more status called "Submitted", there was an old issue that used - # to set it as Submitted, fixed in this commit - frappe.db.sql(""" - update - `tabPurchase Receipt` - set - status = 'To Bill' - where - status = 'Submitted'""") \ No newline at end of file diff --git a/erpnext/patches/v8_7/make_subscription_from_recurring_data.py b/erpnext/patches/v8_7/make_subscription_from_recurring_data.py deleted file mode 100644 index 2932749116f..00000000000 --- a/erpnext/patches/v8_7/make_subscription_from_recurring_data.py +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe -from frappe.utils import today - -def execute(): - frappe.reload_doc('accounts', 'doctype', 'subscription') - frappe.reload_doc('selling', 'doctype', 'sales_order') - frappe.reload_doc('selling', 'doctype', 'quotation') - frappe.reload_doc('buying', 'doctype', 'purchase_order') - frappe.reload_doc('buying', 'doctype', 'supplier_quotation') - frappe.reload_doc('accounts', 'doctype', 'sales_invoice') - frappe.reload_doc('accounts', 'doctype', 'purchase_invoice') - frappe.reload_doc('stock', 'doctype', 'purchase_receipt') - frappe.reload_doc('stock', 'doctype', 'delivery_note') - frappe.reload_doc('accounts', 'doctype', 'journal_entry') - frappe.reload_doc('accounts', 'doctype', 'payment_entry') - - for doctype in ['Sales Order', 'Sales Invoice', 'Purchase Order', 'Purchase Invoice']: - date_field = "transaction_date" - if doctype in ("Sales Invoice", "Purchase Invoice"): - date_field = "posting_date" - - for data in get_data(doctype, date_field): - make_subscription(doctype, data, date_field) - -def get_data(doctype, date_field): - return frappe.db.sql(""" select name, from_date, end_date, recurring_type, recurring_id, - next_date, notify_by_email, notification_email_address, recurring_print_format, - repeat_on_day_of_month, submit_on_creation, docstatus, {0} - from `tab{1}` where is_recurring = 1 and next_date >= %s and docstatus < 2 - order by next_date desc - """.format(date_field, doctype), today(), as_dict=1) - -def make_subscription(doctype, data, date_field): - if data.name == data.recurring_id: - start_date = data.get(date_field) - else: - start_date = frappe.db.get_value(doctype, data.recurring_id, date_field) - - doc = frappe.get_doc({ - 'doctype': 'Subscription', - 'reference_doctype': doctype, - 'reference_document': data.recurring_id, - 'start_date': start_date, - 'end_date': data.end_date, - 'frequency': data.recurring_type, - 'repeat_on_day': data.repeat_on_day_of_month, - 'notify_by_email': data.notify_by_email, - 'recipients': data.notification_email_address, - 'next_schedule_date': data.next_date, - 'submit_on_creation': data.submit_on_creation - }).insert(ignore_permissions=True) - - if data.docstatus == 1: - doc.submit() \ No newline at end of file diff --git a/erpnext/patches/v8_8/__init__.py b/erpnext/patches/v8_8/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/erpnext/patches/v8_8/add_new_fields_in_accounts_settings.py b/erpnext/patches/v8_8/add_new_fields_in_accounts_settings.py deleted file mode 100644 index bd25f15d789..00000000000 --- a/erpnext/patches/v8_8/add_new_fields_in_accounts_settings.py +++ /dev/null @@ -1,9 +0,0 @@ -from __future__ import unicode_literals -import frappe - - -def execute(): - frappe.db.sql( - "INSERT INTO `tabSingles` (`doctype`, `field`, `value`) VALUES ('Accounts Settings', 'allow_stale', '1'), " - "('Accounts Settings', 'stale_days', '1')" - ) diff --git a/erpnext/patches/v8_8/set_bom_rate_as_per_uom.py b/erpnext/patches/v8_8/set_bom_rate_as_per_uom.py deleted file mode 100644 index 5b169cdff2b..00000000000 --- a/erpnext/patches/v8_8/set_bom_rate_as_per_uom.py +++ /dev/null @@ -1,13 +0,0 @@ -# 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.db.sql(""" - update `tabBOM Item` - set rate = rate * conversion_factor - where uom != stock_uom and docstatus < 2 - and conversion_factor not in (0, 1) - """) \ No newline at end of file diff --git a/erpnext/patches/v8_9/__init__.py b/erpnext/patches/v8_9/__init__.py deleted file mode 100644 index 8b137891791..00000000000 --- a/erpnext/patches/v8_9/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/erpnext/patches/v8_9/add_setup_progress_actions.py b/erpnext/patches/v8_9/add_setup_progress_actions.py deleted file mode 100644 index 77501073cf4..00000000000 --- a/erpnext/patches/v8_9/add_setup_progress_actions.py +++ /dev/null @@ -1,47 +0,0 @@ - -from __future__ import unicode_literals -import frappe -from frappe import _ - -def execute(): - """Add setup progress actions""" - if not frappe.db.exists('DocType', 'Setup Progress') or not frappe.db.exists('DocType', 'Setup Progress Action'): - return - - frappe.reload_doc("setup", "doctype", "setup_progress") - frappe.reload_doc("setup", "doctype", "setup_progress_action") - - actions = [ - {"action_name": "Add Company", "action_doctype": "Company", "min_doc_count": 1, "is_completed": 1, - "domains": '[]' }, - {"action_name": "Set Sales Target", "action_doctype": "Company", "min_doc_count": 99, - "action_document": frappe.defaults.get_defaults().get("company") or '', - "action_field": "monthly_sales_target", "is_completed": 0, - "domains": '["Manufacturing", "Services", "Retail", "Distribution"]' }, - {"action_name": "Add Customers", "action_doctype": "Customer", "min_doc_count": 1, "is_completed": 0, - "domains": '["Manufacturing", "Services", "Retail", "Distribution"]' }, - {"action_name": "Add Suppliers", "action_doctype": "Supplier", "min_doc_count": 1, "is_completed": 0, - "domains": '["Manufacturing", "Services", "Retail", "Distribution"]' }, - {"action_name": "Add Products", "action_doctype": "Item", "min_doc_count": 1, "is_completed": 0, - "domains": '["Manufacturing", "Services", "Retail", "Distribution"]' }, - {"action_name": "Add Programs", "action_doctype": "Program", "min_doc_count": 1, "is_completed": 0, - "domains": '["Education"]' }, - {"action_name": "Add Instructors", "action_doctype": "Instructor", "min_doc_count": 1, "is_completed": 0, - "domains": '["Education"]' }, - {"action_name": "Add Courses", "action_doctype": "Course", "min_doc_count": 1, "is_completed": 0, - "domains": '["Education"]' }, - {"action_name": "Add Rooms", "action_doctype": "Room", "min_doc_count": 1, "is_completed": 0, - "domains": '["Education"]' }, - {"action_name": "Add Users", "action_doctype": "User", "min_doc_count": 4, "is_completed": 0, - "domains": '[]' }, - {"action_name": "Add Letterhead", "action_doctype": "Letter Head", "min_doc_count": 1, "is_completed": 0, - "domains": '[]' } - ] - - setup_progress = frappe.get_doc("Setup Progress", "Setup Progress") - setup_progress.actions = [] - for action in actions: - setup_progress.append("actions", action) - - setup_progress.save(ignore_permissions=True) - diff --git a/erpnext/patches/v8_9/delete_gst_doctypes_for_outside_india_accounts.py b/erpnext/patches/v8_9/delete_gst_doctypes_for_outside_india_accounts.py deleted file mode 100644 index f67af90555a..00000000000 --- a/erpnext/patches/v8_9/delete_gst_doctypes_for_outside_india_accounts.py +++ /dev/null @@ -1,14 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - company = frappe.get_all('Company', filters = {'country': 'India'}) - if not company: - if frappe.db.exists("DocType", "GST Settings"): - frappe.delete_doc("DocType", "GST Settings") - frappe.delete_doc("DocType", "GST HSN Code") - - for report_name in ('GST Sales Register', 'GST Purchase Register', - 'GST Itemised Sales Register', 'GST Itemised Purchase Register'): - - frappe.delete_doc('Report', report_name) \ No newline at end of file diff --git a/erpnext/patches/v8_9/remove_employee_from_salary_structure_parent.py b/erpnext/patches/v8_9/remove_employee_from_salary_structure_parent.py deleted file mode 100644 index 808ae6d5271..00000000000 --- a/erpnext/patches/v8_9/remove_employee_from_salary_structure_parent.py +++ /dev/null @@ -1,6 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - if 'employee' in frappe.db.get_table_columns("Salary Structure"): - frappe.db.sql("alter table `tabSalary Structure` drop column employee") diff --git a/erpnext/patches/v8_9/rename_company_sales_target_field.py b/erpnext/patches/v8_9/rename_company_sales_target_field.py deleted file mode 100644 index 5433eb673e4..00000000000 --- a/erpnext/patches/v8_9/rename_company_sales_target_field.py +++ /dev/null @@ -1,8 +0,0 @@ -from __future__ import unicode_literals -import frappe -from frappe.model.utils.rename_field import rename_field - -def execute(): - frappe.reload_doc("setup", "doctype", "company") - if frappe.db.has_column('Company', 'sales_target'): - rename_field("Company", "sales_target", "monthly_sales_target") diff --git a/erpnext/patches/v8_9/set_default_customer_group.py b/erpnext/patches/v8_9/set_default_customer_group.py deleted file mode 100644 index cbbe09daf5d..00000000000 --- a/erpnext/patches/v8_9/set_default_customer_group.py +++ /dev/null @@ -1,8 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - selling_settings = frappe.get_single('Selling Settings') - selling_settings.set_default_customer_group_and_territory() - selling_settings.flags.ignore_mandatory = True - selling_settings.save() diff --git a/erpnext/patches/v8_9/set_default_fields_in_variant_settings.py b/erpnext/patches/v8_9/set_default_fields_in_variant_settings.py deleted file mode 100644 index a550d093fab..00000000000 --- a/erpnext/patches/v8_9/set_default_fields_in_variant_settings.py +++ /dev/null @@ -1,13 +0,0 @@ -# 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('stock', 'doctype', 'item_variant_settings') - frappe.reload_doc('stock', 'doctype', 'variant_field') - - doc = frappe.get_doc('Item Variant Settings') - doc.set_default_fields() - doc.save() \ No newline at end of file diff --git a/erpnext/patches/v8_9/set_member_party_type.py b/erpnext/patches/v8_9/set_member_party_type.py deleted file mode 100644 index 33bbc11a93c..00000000000 --- a/erpnext/patches/v8_9/set_member_party_type.py +++ /dev/null @@ -1,9 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - if not frappe.db.exists("Party Type", "Member"): - frappe.reload_doc("non_profit", "doctype", "member") - party = frappe.new_doc("Party Type") - party.party_type = "Member" - party.save() diff --git a/erpnext/patches/v8_9/set_print_zero_amount_taxes.py b/erpnext/patches/v8_9/set_print_zero_amount_taxes.py deleted file mode 100644 index 3c508eaa097..00000000000 --- a/erpnext/patches/v8_9/set_print_zero_amount_taxes.py +++ /dev/null @@ -1,9 +0,0 @@ -from __future__ import unicode_literals -import frappe - -from erpnext.setup.install import create_print_zero_amount_taxes_custom_field - -def execute(): - frappe.reload_doc('printing', 'doctype', 'print_style') - frappe.reload_doc('printing', 'doctype', 'print_settings') - create_print_zero_amount_taxes_custom_field() \ No newline at end of file diff --git a/erpnext/patches/v8_9/update_billing_gstin_for_indian_account.py b/erpnext/patches/v8_9/update_billing_gstin_for_indian_account.py deleted file mode 100644 index 24e20409c19..00000000000 --- a/erpnext/patches/v8_9/update_billing_gstin_for_indian_account.py +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - company = frappe.get_all('Company', filters = {'country': 'India'}) - - if company: - for doctype in ['Sales Invoice', 'Delivery Note']: - frappe.db.sql(""" update `tab{0}` - set billing_address_gstin = (select gstin from `tabAddress` - where name = customer_address) - where customer_address is not null and customer_address != ''""".format(doctype)) \ No newline at end of file diff --git a/erpnext/patches/v9_0/__init__.py b/erpnext/patches/v9_0/__init__.py deleted file mode 100644 index baffc488252..00000000000 --- a/erpnext/patches/v9_0/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from __future__ import unicode_literals diff --git a/erpnext/patches/v9_0/add_healthcare_domain.py b/erpnext/patches/v9_0/add_healthcare_domain.py deleted file mode 100644 index 3c0433b9d49..00000000000 --- a/erpnext/patches/v9_0/add_healthcare_domain.py +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - domain = 'Healthcare' - if not frappe.db.exists('Domain', domain): - frappe.get_doc({ - 'doctype': 'Domain', - 'domain': domain - }).insert(ignore_permissions=True) \ No newline at end of file diff --git a/erpnext/patches/v9_0/add_user_to_child_table_in_pos_profile.py b/erpnext/patches/v9_0/add_user_to_child_table_in_pos_profile.py deleted file mode 100644 index 8a8c8064dde..00000000000 --- a/erpnext/patches/v9_0/add_user_to_child_table_in_pos_profile.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - if frappe.db.table_exists("POS Profile User"): - frappe.reload_doc('accounts', 'doctype', 'pos_profile_user') - - frappe.db.sql(""" update `tabPOS Profile User`, - (select `tabPOS Profile User`.name from `tabPOS Profile User`, `tabPOS Profile` - where `tabPOS Profile`.name = `tabPOS Profile User`.parent - group by `tabPOS Profile User`.user, `tabPOS Profile`.company) as pfu - set - `tabPOS Profile User`.default = 1 - where `tabPOS Profile User`.name = pfu.name""") - else: - doctype = 'POS Profile' - frappe.reload_doc('accounts', 'doctype', doctype) - frappe.reload_doc('accounts', 'doctype', 'pos_profile_user') - frappe.reload_doc('accounts', 'doctype', 'pos_item_group') - frappe.reload_doc('accounts', 'doctype', 'pos_customer_group') - - for doc in frappe.get_all(doctype): - _doc = frappe.get_doc(doctype, doc.name) - user = frappe.db.get_value(doctype, doc.name, 'user') - - if not user: continue - - _doc.append('applicable_for_users', { - 'user': user, - 'default': 1 - }) - - _doc.flags.ignore_validate = True - _doc.flags.ignore_mandatory = True - _doc.save() \ No newline at end of file diff --git a/erpnext/patches/v9_0/copy_old_fees_field_data.py b/erpnext/patches/v9_0/copy_old_fees_field_data.py deleted file mode 100644 index 14278209c75..00000000000 --- a/erpnext/patches/v9_0/copy_old_fees_field_data.py +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - # 'Schools' module changed to the 'Education' - # frappe.reload_doc("schools", "doctype", "fees") - frappe.reload_doc("education", "doctype", "fees") - - if "total_amount" not in frappe.db.get_table_columns("Fees"): - return - - frappe.db.sql("""update tabFees set grand_total=total_amount where grand_total = 0.0""") \ No newline at end of file diff --git a/erpnext/patches/v9_0/remove_non_existing_warehouse_from_stock_settings.py b/erpnext/patches/v9_0/remove_non_existing_warehouse_from_stock_settings.py deleted file mode 100644 index c685bbc6818..00000000000 --- a/erpnext/patches/v9_0/remove_non_existing_warehouse_from_stock_settings.py +++ /dev/null @@ -1,8 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - default_warehouse = frappe.db.get_value("Stock Settings", None, "default_warehouse") - if default_warehouse: - if not frappe.db.get_value("Warehouse", {"name": default_warehouse}): - frappe.db.set_value("Stock Settings", None, "default_warehouse", "") \ No newline at end of file diff --git a/erpnext/patches/v9_0/remove_subscription_module.py b/erpnext/patches/v9_0/remove_subscription_module.py deleted file mode 100644 index 493873f3e80..00000000000 --- a/erpnext/patches/v9_0/remove_subscription_module.py +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - if frappe.db.exists('Module Def', 'Subscription'): - frappe.db.sql(""" delete from `tabModule Def` where name = 'Subscription'""") \ No newline at end of file diff --git a/erpnext/patches/v9_0/revert_manufacturing_user_role.py b/erpnext/patches/v9_0/revert_manufacturing_user_role.py deleted file mode 100644 index f38b7f29cec..00000000000 --- a/erpnext/patches/v9_0/revert_manufacturing_user_role.py +++ /dev/null @@ -1,22 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - if 'Manufacturing' in frappe.get_active_domains(): return - - role = 'Manufacturing User' - frappe.db.set_value('Role', role, 'restrict_to_domain', '') - frappe.db.set_value('Role', role, 'disabled', 0) - - users = frappe.get_all('Has Role', filters = { - 'parenttype': 'User', - 'role': ('in', ['System Manager', 'Manufacturing Manager']) - }, fields=['parent'], as_list=1) - - for user in users: - _user = frappe.get_doc('User', user[0]) - _user.append('roles', { - 'role': role - }) - _user.flags.ignore_validate = True - _user.save() diff --git a/erpnext/patches/v9_0/set_pos_profile_name.py b/erpnext/patches/v9_0/set_pos_profile_name.py deleted file mode 100644 index a3a97352150..00000000000 --- a/erpnext/patches/v9_0/set_pos_profile_name.py +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - doctype = 'POS Profile' - frappe.reload_doctype(doctype) - - for pos in frappe.get_all(doctype, filters={'disabled': 0}): - doc = frappe.get_doc(doctype, pos.name) - - if not doc.user: continue - - try: - pos_profile_name = doc.user + ' - ' + doc.company - doc.flags.ignore_validate = True - doc.flags.ignore_mandatory = True - doc.save() - - frappe.rename_doc(doctype, doc.name, pos_profile_name, force=True) - except frappe.LinkValidationError: - frappe.db.set_value("POS Profile", doc.name, 'disabled', 1) diff --git a/erpnext/patches/v9_0/set_schedule_date_for_material_request_and_purchase_order.py b/erpnext/patches/v9_0/set_schedule_date_for_material_request_and_purchase_order.py deleted file mode 100644 index 3d012978fab..00000000000 --- a/erpnext/patches/v9_0/set_schedule_date_for_material_request_and_purchase_order.py +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - for doctype in ("Material Request", "Purchase Order"): - frappe.reload_doctype(doctype) - frappe.reload_doctype(doctype + " Item") - - if not frappe.db.has_column(doctype, "schedule_date"): - continue - - #Update only submitted MR - for record in frappe.get_all(doctype, filters= [["docstatus", "=", 1]], fields=["name"]): - doc = frappe.get_doc(doctype, record) - if doc.items: - if not doc.schedule_date: - schedule_dates = [d.schedule_date for d in doc.items if d.schedule_date] - if len(schedule_dates) > 0: - min_schedule_date = min(schedule_dates) - frappe.db.set_value(doctype, record, - "schedule_date", min_schedule_date, update_modified=False) \ No newline at end of file diff --git a/erpnext/patches/v9_0/set_shipping_type_for_existing_shipping_rules.py b/erpnext/patches/v9_0/set_shipping_type_for_existing_shipping_rules.py deleted file mode 100644 index 5092695b7d9..00000000000 --- a/erpnext/patches/v9_0/set_shipping_type_for_existing_shipping_rules.py +++ /dev/null @@ -1,18 +0,0 @@ -# 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_doctype("Shipping Rule") - - # default "calculate_based_on" - frappe.db.sql('''update `tabShipping Rule` - set calculate_based_on = "Net Weight" - where ifnull(calculate_based_on, '') = '' ''') - - # default "shipping_rule_type" - frappe.db.sql('''update `tabShipping Rule` - set shipping_rule_type = "Selling" - where ifnull(shipping_rule_type, '') = '' ''') diff --git a/erpnext/patches/v9_0/set_uoms_in_variant_field.py b/erpnext/patches/v9_0/set_uoms_in_variant_field.py deleted file mode 100644 index 9e783d99beb..00000000000 --- a/erpnext/patches/v9_0/set_uoms_in_variant_field.py +++ /dev/null @@ -1,14 +0,0 @@ -from __future__ import unicode_literals -import frappe - - -def execute(): - doc = frappe.get_doc('Item Variant Settings') - variant_field_names = [vf.field_name for vf in doc.fields] - if 'uoms' not in variant_field_names: - doc.append( - 'fields', { - 'field_name': 'uoms' - } - ) - doc.save() diff --git a/erpnext/patches/v9_0/set_variant_item_description.py b/erpnext/patches/v9_0/set_variant_item_description.py deleted file mode 100644 index 82d6148508a..00000000000 --- a/erpnext/patches/v9_0/set_variant_item_description.py +++ /dev/null @@ -1,46 +0,0 @@ -from __future__ import unicode_literals -import frappe -from frappe.utils import cstr - -def execute(): - ''' - Issue: - While copying data from template item to variant item, - the system appending description multiple times to the respective variant. - - Purpose: - Check variant description, - if variant have user defined description remove all system appended descriptions - else replace multiple system generated descriptions with single description - - Steps: - 1. Get all variant items - 2. Create system generated variant description - 3. If variant have user defined description, remove all system generated descriptions - 4. If variant description only contains system generated description, - replace multiple descriptions by new description. - ''' - for item in frappe.db.sql(""" select name from tabItem - where ifnull(variant_of, '') != '' """,as_dict=1): - variant = frappe.get_doc("Item", item.name) - temp_variant_description = '\n' - - if variant.attributes: - for d in variant.attributes: - temp_variant_description += "
    " + d.attribute + ": " + cstr(d.attribute_value) + "
    " - - variant_description = variant.description.replace(temp_variant_description, '').rstrip() - if variant_description: - splitted_desc = variant.description.strip().split(temp_variant_description) - - if len(splitted_desc) > 2: - if splitted_desc[0] == '': - variant_description = temp_variant_description + variant_description - elif splitted_desc[1] == '' or splitted_desc[1] == '\n': - variant_description += temp_variant_description - variant.db_set('description', variant_description, update_modified=False) - else: - variant.db_set('description', variant_description, update_modified=False) - - else: - variant.db_set('description', temp_variant_description, update_modified=False) \ No newline at end of file diff --git a/erpnext/patches/v9_0/student_admission_childtable_migrate.py b/erpnext/patches/v9_0/student_admission_childtable_migrate.py deleted file mode 100644 index a5712c76dcc..00000000000 --- a/erpnext/patches/v9_0/student_admission_childtable_migrate.py +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - # 'Schools' module changed to the 'Education' - # frappe.reload_doc('schools', 'doctype', 'Student Admission Program') - # frappe.reload_doc('schools', 'doctype', 'student_admission') - frappe.reload_doc('education', 'doctype', 'Student Admission Program') - frappe.reload_doc('education', 'doctype', 'student_admission') - - if "program" not in frappe.db.get_table_columns("Student Admission"): - return - - student_admissions = frappe.get_all("Student Admission", fields=["name", "application_fee", \ - "naming_series_for_student_applicant", "program", "introduction", "eligibility"]) - for student_admission in student_admissions: - doc = frappe.get_doc("Student Admission", student_admission.name) - doc.append("program_details", { - "program": student_admission.get("program"), - "application_fee": student_admission.get("application_fee"), - "applicant_naming_series": student_admission.get("naming_series_for_student_applicant"), - }) - if student_admission.eligibility and student_admission.introduction: - doc.introduction = student_admission.introduction + "
    " + \ - student_admission.eligibility + "
    " - doc.flags.ignore_validate = True - doc.flags.ignore_mandatory = True - doc.save() diff --git a/erpnext/patches/v9_0/update_employee_loan_details.py b/erpnext/patches/v9_0/update_employee_loan_details.py deleted file mode 100644 index ef8d32855fb..00000000000 --- a/erpnext/patches/v9_0/update_employee_loan_details.py +++ /dev/null @@ -1,24 +0,0 @@ -# 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('Payroll', 'doctype', 'salary_slip_loan') - frappe.reload_doc('Payroll', 'doctype', 'salary_slip') - - for data in frappe.db.sql(""" select name, - start_date, end_date, total_loan_repayment - from - `tabSalary Slip` - where - docstatus < 2 and ifnull(total_loan_repayment, 0) > 0""", as_dict=1): - salary_slip = frappe.get_doc('Salary Slip', data.name) - salary_slip.set_loan_repayment() - - if salary_slip.total_loan_repayment == data.total_loan_repayment: - for row in salary_slip.loans: - row.db_update() - - salary_slip.db_update() diff --git a/erpnext/patches/v9_0/update_multi_uom_fields_in_material_request.py b/erpnext/patches/v9_0/update_multi_uom_fields_in_material_request.py deleted file mode 100644 index 45610ed5a73..00000000000 --- a/erpnext/patches/v9_0/update_multi_uom_fields_in_material_request.py +++ /dev/null @@ -1,12 +0,0 @@ -# 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_doctype('Material Request') - frappe.reload_doctype('Material Request Item') - - frappe.db.sql(""" update `tabMaterial Request Item` - set stock_uom = uom, stock_qty = qty, conversion_factor = 1.0""") \ No newline at end of file diff --git a/erpnext/patches/v9_1/__init__.py b/erpnext/patches/v9_1/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/erpnext/patches/v9_1/create_issue_opportunity_type.py b/erpnext/patches/v9_1/create_issue_opportunity_type.py deleted file mode 100644 index aa8bbd1e799..00000000000 --- a/erpnext/patches/v9_1/create_issue_opportunity_type.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe -from frappe import _ - -def execute(): - # delete custom field if exists - for doctype, fieldname in (('Issue', 'issue_type'), ('Opportunity', 'opportunity_type')): - custom_field = frappe.db.get_value("Custom Field", {"fieldname": fieldname, 'dt': doctype}) - if custom_field: - frappe.delete_doc("Custom Field", custom_field, ignore_permissions=True) - - frappe.reload_doc('support', 'doctype', 'issue_type') - frappe.reload_doc('support', 'doctype', 'issue') - frappe.reload_doc('crm', 'doctype', 'opportunity_type') - frappe.reload_doc('crm', 'doctype', 'opportunity') - - # rename enquiry_type -> opportunity_type - from frappe.model.utils.rename_field import rename_field - rename_field('Opportunity', 'enquiry_type', 'opportunity_type') - - # create values if already set - for opts in (('Issue', 'issue_type', 'Issue Type'), - ('Opportunity', 'opportunity_type', 'Opportunity Type')): - for d in frappe.db.sql('select distinct {0} from `tab{1}`'.format(opts[1], opts[0])): - if d[0] and not frappe.db.exists(opts[2], d[0]): - frappe.get_doc(dict(doctype = opts[2], name=d[0])).insert() - - # fixtures - for name in ('Hub', _('Sales'), _('Support'), _('Maintenance')): - if not frappe.db.exists('Opportunity Type', name): - frappe.get_doc(dict(doctype = 'Opportunity Type', name=name)).insert() diff --git a/erpnext/patches/v9_2/__init__.py b/erpnext/patches/v9_2/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/erpnext/patches/v9_2/delete_healthcare_domain_default_items.py b/erpnext/patches/v9_2/delete_healthcare_domain_default_items.py deleted file mode 100644 index 54ae18b8e29..00000000000 --- a/erpnext/patches/v9_2/delete_healthcare_domain_default_items.py +++ /dev/null @@ -1,17 +0,0 @@ -from __future__ import unicode_literals -import frappe -from frappe.utils import getdate - -def execute(): - domain_settings = frappe.get_doc('Domain Settings') - active_domains = [d.domain for d in domain_settings.active_domains] - - if "Healthcare" not in active_domains: - items = ["TTT", "MCH", "LDL", "GTT", "HDL", "BILT", "BILD", "BP", "BS"] - for item_code in items: - try: - item = frappe.db.get_value("Item", {"item_code": item_code}, ["name", "creation"], as_dict=1) - if item and getdate(item.creation) >= getdate("2017-11-10"): - frappe.delete_doc("Item", item.name) - except: - pass \ No newline at end of file diff --git a/erpnext/patches/v9_2/delete_process_payroll.py b/erpnext/patches/v9_2/delete_process_payroll.py deleted file mode 100644 index 91c49f577f3..00000000000 --- a/erpnext/patches/v9_2/delete_process_payroll.py +++ /dev/null @@ -1,5 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.delete_doc("DocType", "Process Payroll") diff --git a/erpnext/patches/v9_2/remove_company_from_patient.py b/erpnext/patches/v9_2/remove_company_from_patient.py deleted file mode 100644 index 1a50088f239..00000000000 --- a/erpnext/patches/v9_2/remove_company_from_patient.py +++ /dev/null @@ -1,7 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - if frappe.db.exists("DocType", "Patient"): - if 'company' in frappe.db.get_table_columns("Patient"): - frappe.db.sql("alter table `tabPatient` drop column company") diff --git a/erpnext/patches/v9_2/rename_net_weight_in_item_master.py b/erpnext/patches/v9_2/rename_net_weight_in_item_master.py deleted file mode 100644 index cad979deaba..00000000000 --- a/erpnext/patches/v9_2/rename_net_weight_in_item_master.py +++ /dev/null @@ -1,8 +0,0 @@ -from __future__ import unicode_literals -import frappe -from frappe.model.utils.rename_field import rename_field - -def execute(): - frappe.reload_doc("stock", "doctype", "item") - if frappe.db.has_column('Item', 'net_weight'): - rename_field("Item", "net_weight", "weight_per_unit") diff --git a/erpnext/patches/v9_2/rename_translated_domains_in_en.py b/erpnext/patches/v9_2/rename_translated_domains_in_en.py deleted file mode 100644 index e5a9e2461fa..00000000000 --- a/erpnext/patches/v9_2/rename_translated_domains_in_en.py +++ /dev/null @@ -1,39 +0,0 @@ -from __future__ import unicode_literals -import frappe -from frappe import _ -from frappe.model.rename_doc import rename_doc - -def execute(): - frappe.reload_doc('stock', 'doctype', 'item') - language = frappe.get_single("System Settings").language - - if language and language.startswith('en'): return - - frappe.local.lang = language - - all_domains = frappe.get_hooks("domains") - - for domain in all_domains: - translated_domain = _(domain, lang=language) - if frappe.db.exists("Domain", translated_domain): - #if domain already exists merged translated_domain and domain - merge = False - if frappe.db.exists("Domain", domain): - merge=True - - rename_doc("Domain", translated_domain, domain, ignore_permissions=True, merge=merge) - - domain_settings = frappe.get_single("Domain Settings") - active_domains = [d.domain for d in domain_settings.active_domains] - - try: - for domain in active_domains: - domain = frappe.get_doc("Domain", domain) - domain.setup_domain() - - if int(frappe.db.get_single_value('System Settings', 'setup_complete')): - domain.setup_sidebar_items() - domain.setup_desktop_icons() - domain.set_default_portal_role() - except frappe.LinkValidationError: - pass \ No newline at end of file diff --git a/erpnext/patches/v9_2/repost_reserved_qty_for_production.py b/erpnext/patches/v9_2/repost_reserved_qty_for_production.py deleted file mode 100644 index 040e655bd82..00000000000 --- a/erpnext/patches/v9_2/repost_reserved_qty_for_production.py +++ /dev/null @@ -1,9 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - frappe.reload_doc("stock", "doctype", "bin") - bins = frappe.db.sql("select name from `tabBin` where reserved_qty_for_production > 0") - for d in bins: - bin_doc = frappe.get_doc("Bin", d[0]) - bin_doc.update_reserved_qty_for_production() diff --git a/erpnext/patches/v9_2/set_item_name_in_production_order.py b/erpnext/patches/v9_2/set_item_name_in_production_order.py deleted file mode 100644 index 1f490e62c8b..00000000000 --- a/erpnext/patches/v9_2/set_item_name_in_production_order.py +++ /dev/null @@ -1,12 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - - frappe.db.sql(""" - update `tabBOM Item` bom, `tabWork Order Item` po_item - set po_item.item_name = bom.item_name, - po_item.description = bom.description - where po_item.item_code = bom.item_code - and (po_item.item_name is null or po_item.description is null) - """) From 8697e894419181e90868732db023d39e7561a58a Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Fri, 4 Jun 2021 11:47:09 +0530 Subject: [PATCH 109/135] chore: Drop < v10 patches from list v7 backup was restored and upgraded to latest v10.x.x branch. The patches run uptil the upgrade are removed in this change. This means only existing v10 sites are allowed direct upgrade to v13 and newer There are older version patches still left since they're being used in later ERPNext versions too. --- erpnext/patches.txt | 495 -------------------------------------------- 1 file changed, 495 deletions(-) diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 1e8ce3c6583..770bef353f2 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -1,494 +1,19 @@ -execute:import unidecode # new requirement -erpnext.patches.v8_0.move_perpetual_inventory_setting -erpnext.patches.v8_9.set_print_zero_amount_taxes erpnext.patches.v12_0.update_is_cancelled_field erpnext.patches.v11_0.rename_production_order_to_work_order erpnext.patches.v11_0.refactor_naming_series erpnext.patches.v11_0.refactor_autoname_naming -erpnext.patches.v10_0.rename_schools_to_education -erpnext.patches.v4_0.validate_v3_patch -erpnext.patches.v4_0.fix_employee_user_id -erpnext.patches.v4_0.remove_employee_role_if_no_employee -erpnext.patches.v4_0.update_user_properties -erpnext.patches.v4_0.apply_user_permissions -erpnext.patches.v4_0.move_warehouse_user_to_restrictions -erpnext.patches.v4_0.global_defaults_to_system_settings -erpnext.patches.v4_0.update_incharge_name_to_sales_person_in_maintenance_schedule execute:frappe.reload_doc("accounts", "doctype", "POS Payment Method") #2020-05-28 execute:frappe.reload_doc("HR", "doctype", "HR Settings") #2020-01-16 #2020-07-24 -execute:frappe.reload_doc('stock', 'doctype', 'warehouse') # 2017-04-24 -execute:frappe.reload_doc('accounts', 'doctype', 'sales_invoice') # 2016-08-31 -execute:frappe.reload_doc('selling', 'doctype', 'sales_order') # 2014-01-29 -execute:frappe.reload_doc('selling', 'doctype', 'quotation') # 2014-01-29 -execute:frappe.reload_doc('stock', 'doctype', 'delivery_note') # 2014-01-29 -erpnext.patches.v4_0.reload_sales_print_format -execute:frappe.reload_doc('accounts', 'doctype', 'purchase_invoice') # 2014-01-29 -execute:frappe.reload_doc('buying', 'doctype', 'purchase_order') # 2014-01-29 -execute:frappe.reload_doc('buying', 'doctype', 'supplier_quotation') # 2014-01-29 -execute:frappe.reload_doc('stock', 'doctype', 'purchase_receipt') # 2014-01-29 -execute:frappe.reload_doc('accounts', 'doctype', 'pos_setting') # 2014-01-29 -execute:frappe.reload_doc('selling', 'doctype', 'customer') # 2014-01-29 -execute:frappe.reload_doc('buying', 'doctype', 'supplier') # 2014-01-29 -execute:frappe.reload_doc('accounts', 'doctype', 'asset_category') -execute:frappe.reload_doc('accounts', 'doctype', 'pricing_rule') -erpnext.patches.v4_0.map_charge_to_taxes_and_charges -execute:frappe.reload_doc('support', 'doctype', 'newsletter') # 2014-01-31 -execute:frappe.reload_doc('hr', 'doctype', 'employee') # 2014-02-03 -execute:frappe.db.sql("update tabPage set module='Core' where name='Setup'") -erpnext.patches.v5_2.change_item_selects_to_checks -execute:frappe.reload_doctype('Item') -erpnext.patches.v4_0.fields_to_be_renamed -erpnext.patches.v4_0.rename_sitemap_to_route -erpnext.patches.v7_0.re_route #2016-06-27 -erpnext.patches.v4_0.fix_contact_address -erpnext.patches.v4_0.customer_discount_to_pricing_rule -execute:frappe.db.sql("""delete from `tabWebsite Item Group` where ifnull(item_group, '')=''""") -erpnext.patches.v4_0.remove_module_home_pages -erpnext.patches.v4_0.split_email_settings -erpnext.patches.v4_0.import_country_codes -erpnext.patches.v4_0.countrywise_coa -execute:frappe.delete_doc("DocType", "MIS Control") -execute:frappe.delete_doc("Page", "Financial Statements") -execute:frappe.delete_doc("DocType", "Stock Ledger") -execute:frappe.delete_doc("DocType", "Grade") -execute:frappe.db.sql("delete from `tabWebsite Item Group` where ifnull(item_group, '')=''") -execute:frappe.delete_doc("Print Format", "SalesInvoice") -execute:import frappe.defaults;frappe.defaults.clear_default("price_list_currency") -erpnext.patches.v4_0.update_account_root_type -execute:frappe.delete_doc("Report", "Purchase In Transit") -erpnext.patches.v4_0.new_address_template -execute:frappe.delete_doc("DocType", "SMS Control") -execute:frappe.delete_doc_if_exists("DocType", "Bulk SMS") #2015-08-18 -erpnext.patches.v4_0.fix_case_of_hr_module_def -erpnext.patches.v4_0.fix_address_template - -# WATCHOUT: This patch reload's documents -erpnext.patches.v4_0.reset_permissions_for_masters -erpnext.patches.v6_20x.rename_project_name_to_project #2016-03-14 - -erpnext.patches.v4_0.update_tax_amount_after_discount -execute:frappe.permissions.reset_perms("GL Entry") #2014-06-09 -execute:frappe.permissions.reset_perms("Stock Ledger Entry") #2014-06-09 -erpnext.patches.v4_0.create_custom_fields_for_india_specific_fields -erpnext.patches.v4_0.save_default_letterhead -erpnext.patches.v4_0.update_custom_print_formats_for_renamed_fields -erpnext.patches.v4_0.update_other_charges_in_custom_purchase_print_formats -erpnext.patches.v4_0.create_price_list_if_missing -execute:frappe.db.sql("update `tabItem` set end_of_life=null where end_of_life='0000-00-00'") #2014-06-16 -erpnext.patches.v4_0.update_users_report_view_settings -erpnext.patches.v4_0.set_pricing_rule_for_buying_or_selling -erpnext.patches.v4_1.set_outgoing_email_footer -erpnext.patches.v4_1.fix_sales_order_delivered_status -erpnext.patches.v4_1.fix_delivery_and_billing_status -execute:frappe.db.sql("update `tabAccount` set root_type='Liability' where root_type='Income' and report_type='Balance Sheet'") -execute:frappe.delete_doc("DocType", "Payment to Invoice Matching Tool") # 29-07-2014 -execute:frappe.delete_doc("DocType", "Payment to Invoice Matching Tool Detail") # 29-07-2014 -execute:frappe.delete_doc("Page", "trial-balance") #2014-07-22 -erpnext.patches.v4_2.delete_old_print_formats #2014-07-29 -erpnext.patches.v4_2.toggle_rounded_total #2014-07-30 -erpnext.patches.v4_2.fix_account_master_type -erpnext.patches.v4_2.update_project_milestones -erpnext.patches.v4_2.add_currency_turkish_lira #2014-08-08 -execute:frappe.delete_doc("DocType", "Landed Cost Wizard") -erpnext.patches.v4_2.default_website_style -erpnext.patches.v4_2.set_company_country -erpnext.patches.v4_2.update_sales_order_invoice_field_name -erpnext.patches.v4_2.seprate_manufacture_and_repack -execute:frappe.delete_doc("Report", "Warehouse-Wise Stock Balance") -execute:frappe.delete_doc("DocType", "Purchase Request") -execute:frappe.delete_doc("DocType", "Purchase Request Item") -erpnext.patches.v4_2.recalculate_bom_cost -erpnext.patches.v4_2.fix_gl_entries_for_stock_transactions erpnext.patches.v4_2.update_requested_and_ordered_qty #2021-03-31 -execute:frappe.rename_doc("DocType", "Support Ticket", "Issue", force=True) -erpnext.patches.v4_4.make_email_accounts -execute:frappe.delete_doc("DocType", "Contact Control") -erpnext.patches.v4_2.discount_amount -erpnext.patches.v4_2.reset_bom_costs -erpnext.patches.v5_0.update_frozen_accounts_permission_role -erpnext.patches.v5_0.update_dn_against_doc_fields -execute:frappe.db.sql("update `tabMaterial Request` set material_request_type = 'Material Transfer' where material_request_type = 'Transfer'") -execute:frappe.reload_doc('stock', 'doctype', 'item') -erpnext.patches.v5_0.set_default_company_in_bom -execute:frappe.reload_doc('crm', 'doctype', 'lead') -execute:frappe.reload_doc('crm', 'doctype', 'opportunity') -erpnext.patches.v5_0.rename_taxes_and_charges_master -erpnext.patches.v5_1.sales_bom_rename -erpnext.patches.v5_0.rename_table_fieldnames -execute:frappe.db.sql("update `tabJournal Entry` set voucher_type='Journal Entry' where ifnull(voucher_type, '')=''") -erpnext.patches.v5_0.is_group -erpnext.patches.v4_2.party_model -erpnext.patches.v5_0.party_model_patch_fix -erpnext.patches.v4_1.fix_jv_remarks -erpnext.patches.v4_2.update_landed_cost_voucher -erpnext.patches.v4_2.set_item_has_batch -erpnext.patches.v4_2.update_stock_uom_for_dn_in_sle -erpnext.patches.v5_0.recalculate_total_amount_in_jv -erpnext.patches.v5_0.update_companywise_payment_account -erpnext.patches.v5_0.remove_birthday_events -erpnext.patches.v5_0.update_item_name_in_bom -erpnext.patches.v5_0.rename_customer_issue -erpnext.patches.v5_0.rename_total_fields -erpnext.patches.v5_0.new_crm_module -erpnext.patches.v5_0.rename_customer_issue -erpnext.patches.v5_0.update_material_transfer_for_manufacture -execute:frappe.reload_doc('crm', 'doctype', 'opportunity_item') -erpnext.patches.v5_0.update_item_description_and_image -erpnext.patches.v5_0.update_material_transferred_for_manufacturing -erpnext.patches.v5_0.stock_entry_update_value -erpnext.patches.v5_0.convert_stock_reconciliation -erpnext.patches.v5_0.update_projects -erpnext.patches.v5_0.item_patches -erpnext.patches.v5_0.update_journal_entry_title -erpnext.patches.v5_0.taxes_and_totals_in_party_currency -erpnext.patches.v5_0.replace_renamed_fields_in_custom_scripts_and_print_formats -erpnext.patches.v5_0.update_from_bom -erpnext.patches.v5_0.update_account_types -erpnext.patches.v5_0.update_sms_sender -erpnext.patches.v5_0.set_appraisal_remarks -erpnext.patches.v5_0.update_time_log_title -erpnext.patches.v7_0.create_warehouse_nestedset -erpnext.patches.v7_0.merge_account_type_stock_and_warehouse_to_stock -erpnext.patches.v7_0.set_is_group_for_warehouse -erpnext.patches.v7_2.stock_uom_in_selling -erpnext.patches.v4_2.repost_sle_for_si_with_no_warehouse -erpnext.patches.v5_0.newsletter -execute:frappe.delete_doc("DocType", "Chart of Accounts") -execute:frappe.delete_doc("DocType", "Style Settings") -erpnext.patches.v5_0.update_opportunity -erpnext.patches.v5_0.opportunity_not_submittable -execute:frappe.permissions.reset_perms("Purchase Taxes and Charges Template") #2014-06-09 -execute:frappe.permissions.reset_perms("Expense Claim Type") #2014-06-19 -erpnext.patches.v5_0.execute_on_doctype_update -erpnext.patches.v4_2.fix_recurring_orders -erpnext.patches.v4_2.delete_gl_entries_for_cancelled_invoices -erpnext.patches.v5_0.project_costing -erpnext.patches.v5_0.update_temporary_account -erpnext.patches.v5_0.update_advance_paid -erpnext.patches.v5_0.link_warehouse_with_account -execute:frappe.delete_doc("Page", "stock-ledger") -execute:frappe.delete_doc("Page","stock-level") -erpnext.patches.v5_0.reclculate_planned_operating_cost_in_production_order -erpnext.patches.v5_0.repost_requested_qty -erpnext.patches.v5_0.fix_taxes_and_totals_in_party_currency -erpnext.patches.v5_0.update_tax_amount_after_discount_in_purchase_cycle -erpnext.patches.v5_0.rename_pos_setting -erpnext.patches.v5_0.update_operation_description -erpnext.patches.v5_0.set_footer_address -execute:frappe.db.set_value("Backup Manager", None, "send_backups_to_dropbox", 1 if frappe.db.get_value("Backup Manager", None, "upload_backups_to_dropbox") in ("Daily", "Weekly") else 0) -execute:frappe.db.sql_list("delete from `tabDocPerm` where parent='Issue' and modified_by='Administrator' and role='Guest'") -erpnext.patches.v5_0.update_item_and_description_again -erpnext.patches.v6_0.multi_currency -erpnext.patches.v7_0.create_budget_record -erpnext.patches.v5_0.repost_gle_for_jv_with_multiple_party -erpnext.patches.v5_0.portal_fixes -erpnext.patches.v5_0.reset_values_in_tools # 02-05-2016 -execute:frappe.delete_doc("Page", "users") -erpnext.patches.v5_0.update_material_transferred_for_manufacturing_again -erpnext.patches.v5_0.index_on_account_and_gl_entry -execute:frappe.db.sql("""delete from `tabProject Task`""") -erpnext.patches.v5_0.update_item_desc_in_invoice -erpnext.patches.v5_1.fix_against_account -execute:frappe.rename_doc("DocType", "Salary Manager", "Process Payroll", force=True) -erpnext.patches.v5_1.rename_roles -erpnext.patches.v5_1.default_bom -execute:frappe.delete_doc("DocType", "Party Type") -execute:frappe.delete_doc("Module Def", "Contacts") -erpnext.patches.v5_4.fix_reserved_qty_and_sle_for_packed_items # 30-07-2015 -execute:frappe.reload_doctype("Leave Type") -execute:frappe.db.sql("update `tabLeave Type` set include_holiday=0") -erpnext.patches.v5_4.set_root_and_report_type -erpnext.patches.v5_4.notify_system_managers_regarding_wrong_tax_calculation -erpnext.patches.v5_4.fix_invoice_outstanding -execute:frappe.db.sql("update `tabStock Ledger Entry` set stock_queue = '[]' where voucher_type = 'Stock Reconciliation' and ifnull(qty_after_transaction, 0) = 0") -erpnext.patches.v5_4.fix_missing_item_images -erpnext.patches.v5_4.stock_entry_additional_costs -erpnext.patches.v5_4.cleanup_journal_entry #2015-08-14 erpnext.patches.v5_7.update_item_description_based_on_item_master -erpnext.patches.v5_7.item_template_attributes -execute:frappe.delete_doc_if_exists("DocType", "Manage Variants") -execute:frappe.delete_doc_if_exists("DocType", "Manage Variants Item") erpnext.patches.v4_2.repost_reserved_qty #2021-03-31 -erpnext.patches.v5_4.update_purchase_cost_against_project -erpnext.patches.v5_8.update_order_reference_in_return_entries -erpnext.patches.v5_8.add_credit_note_print_heading -execute:frappe.delete_doc_if_exists("Print Format", "Credit Note - Negative Invoice") - -# V6.0 -erpnext.patches.v6_0.set_default_title # 2015-09-03 -erpnext.patches.v6_0.default_activity_rate -execute:frappe.db.set_value("Stock Settings", None, "automatically_set_serial_nos_based_on_fifo", 1) -execute:frappe.db.sql("""update `tabProject` set percent_complete=round(percent_complete, 2) where percent_complete is not null""") -erpnext.patches.v6_0.fix_outstanding_amount -erpnext.patches.v6_0.fix_planned_qty -erpnext.patches.v6_2.remove_newsletter_duplicates -erpnext.patches.v6_2.fix_missing_default_taxes_and_lead -erpnext.patches.v6_3.convert_applicable_territory -erpnext.patches.v6_4.round_status_updater_percentages -erpnext.patches.v6_4.repost_gle_for_journal_entries_where_reference_name_missing -erpnext.patches.v6_4.fix_journal_entries_due_to_reconciliation -erpnext.patches.v6_4.fix_status_in_sales_and_purchase_order -erpnext.patches.v6_4.fix_modified_in_sales_order_and_purchase_order -erpnext.patches.v6_4.fix_duplicate_bins -erpnext.patches.v6_4.fix_sales_order_maintenance_status -erpnext.patches.v6_4.email_digest_update - -# delete shopping cart doctypes -execute:frappe.delete_doc_if_exists("DocType", "Applicable Territory") -execute:frappe.delete_doc_if_exists("DocType", "Shopping Cart Price List") -execute:frappe.delete_doc_if_exists("DocType", "Shopping Cart Taxes and Charges Master") - -erpnext.patches.v6_4.set_user_in_contact -erpnext.patches.v6_4.make_image_thumbnail #2015-10-20 -erpnext.patches.v6_5.show_in_website_for_template_item -erpnext.patches.v6_4.fix_expense_included_in_valuation -execute:frappe.delete_doc_if_exists("Report", "Item-wise Last Purchase Rate") -erpnext.patches.v6_6.fix_website_image -erpnext.patches.v6_6.remove_fiscal_year_from_leave_allocation -execute:frappe.delete_doc_if_exists("DocType", "Stock UOM Replace Utility") -erpnext.patches.v6_8.make_webform_standard #2015-11-23 -erpnext.patches.v6_8.move_drop_ship_to_po_items -erpnext.patches.v6_10.fix_ordered_received_billed -erpnext.patches.v6_10.fix_jv_total_amount #2015-11-30 -erpnext.patches.v6_10.email_digest_default_quote -erpnext.patches.v6_10.fix_billed_amount_in_drop_ship_po -erpnext.patches.v6_10.fix_delivery_status_of_drop_ship_item #2015-12-08 -erpnext.patches.v5_8.tax_rule #2015-12-08 -erpnext.patches.v6_12.set_overdue_tasks -erpnext.patches.v6_16.update_billing_status_in_dn_and_pr -erpnext.patches.v6_16.create_manufacturer_records -execute:frappe.db.sql("update `tabPricing Rule` set title=name where title='' or title is null") #2016-01-27 -erpnext.patches.v6_20.set_party_account_currency_in_orders -erpnext.patches.v6_19.comment_feed_communication -erpnext.patches.v6_21.fix_reorder_level -erpnext.patches.v6_21.rename_material_request_fields -erpnext.patches.v6_23.update_stopped_status_to_closed -erpnext.patches.v6_24.set_recurring_id -erpnext.patches.v6_20x.set_compact_print -execute:frappe.delete_doc_if_exists("Web Form", "contact") #2016-03-10 -erpnext.patches.v6_20x.remove_fiscal_year_from_holiday_list -erpnext.patches.v6_24.map_customer_address_to_shipping_address_on_po -erpnext.patches.v6_27.fix_recurring_order_status -erpnext.patches.v6_20x.update_product_bundle_description -erpnext.patches.v7_0.update_party_status #2016-09-22 -erpnext.patches.v7_0.remove_features_setup -erpnext.patches.v7_0.update_home_page -execute:frappe.delete_doc_if_exists("Page", "financial-analytics") -erpnext.patches.v7_0.update_project_in_gl_entry -execute:frappe.db.sql('update tabQuotation set status="Cancelled" where docstatus=2') -execute:frappe.rename_doc("DocType", "Payments", "Sales Invoice Payment", force=True) -erpnext.patches.v7_0.update_mins_to_first_response -erpnext.patches.v6_20x.repost_valuation_rate_for_negative_inventory -erpnext.patches.v7_0.migrate_mode_of_payments_v6_to_v7 -erpnext.patches.v7_0.system_settings_setup_complete -erpnext.patches.v7_0.set_naming_series_for_timesheet #2016-07-27 -execute:frappe.reload_doc('projects', 'doctype', 'project') -execute:frappe.reload_doc('projects', 'doctype', 'project_user') -erpnext.patches.v7_0.convert_timelogbatch_to_timesheet -erpnext.patches.v7_0.convert_timelog_to_timesheet -erpnext.patches.v7_0.move_timelogbatch_from_salesinvoiceitem_to_salesinvoicetimesheet -erpnext.patches.v7_0.remove_doctypes_and_reports #2016-10-29 -erpnext.patches.v7_0.update_maintenance_module_in_doctype -erpnext.patches.v7_0.update_prevdoc_values_for_supplier_quotation_item -erpnext.patches.v7_0.rename_advance_table_fields -erpnext.patches.v7_0.rename_salary_components -erpnext.patches.v7_0.rename_prevdoc_fields -erpnext.patches.v7_0.rename_time_sheet_doctype -execute:frappe.delete_doc_if_exists("Report", "Customers Not Buying Since Long Time") -erpnext.patches.v7_0.make_is_group_fieldtype_as_check -execute:frappe.reload_doc('projects', 'doctype', 'timesheet') #2016-09-12 -erpnext.patches.v7_1.rename_field_timesheet -execute:frappe.delete_doc_if_exists("Report", "Employee Holiday Attendance") -execute:frappe.delete_doc_if_exists("DocType", "Payment Tool") -execute:frappe.delete_doc_if_exists("DocType", "Payment Tool Detail") -erpnext.patches.v7_0.setup_account_table_for_expense_claim_type_if_exists -erpnext.patches.v7_0.migrate_schools_to_erpnext -erpnext.patches.v7_1.update_lead_source -erpnext.patches.v6_20x.remove_customer_supplier_roles -erpnext.patches.v7_0.remove_administrator_role_in_doctypes -erpnext.patches.v7_0.rename_fee_amount_to_fee_component -erpnext.patches.v7_0.calculate_total_costing_amount -erpnext.patches.v7_0.fix_nonwarehouse_ledger_gl_entries_for_transactions -erpnext.patches.v7_0.remove_old_earning_deduction_doctypes -erpnext.patches.v7_0.make_guardian -erpnext.patches.v7_0.update_refdoc_in_landed_cost_voucher -erpnext.patches.v7_0.set_material_request_type_in_item -erpnext.patches.v7_0.rename_examination_to_assessment -erpnext.patches.v7_0.set_portal_settings -erpnext.patches.v7_0.update_change_amount_account -erpnext.patches.v7_0.fix_duplicate_icons -erpnext.patches.v7_0.repost_gle_for_pos_sales_return -erpnext.patches.v7_1.update_total_billing_hours -erpnext.patches.v7_1.update_component_type -erpnext.patches.v7_0.repost_gle_for_pos_sales_return -erpnext.patches.v7_0.update_missing_employee_in_timesheet -erpnext.patches.v7_0.update_status_for_timesheet -erpnext.patches.v7_0.set_party_name_in_payment_entry -erpnext.patches.v7_1.set_student_guardian -erpnext.patches.v7_0.update_conversion_factor_in_supplier_quotation_item -erpnext.patches.v7_1.move_sales_invoice_from_parent_to_child_timesheet -execute:frappe.db.sql("update `tabTimesheet` ts, `tabEmployee` emp set ts.employee_name = emp.employee_name where emp.name = ts.employee and ts.employee_name is null and ts.employee is not null") -erpnext.patches.v7_1.fix_link_for_customer_from_lead -execute:frappe.db.sql("delete from `tabTimesheet Detail` where NOT EXISTS (select name from `tabTimesheet` where name = `tabTimesheet Detail`.parent)") -erpnext.patches.v7_0.update_mode_of_payment_type - -execute:frappe.reload_doctype('Employee') #2016-10-18 -execute:frappe.db.sql("update `tabEmployee` set prefered_contact_email = IFNULL(prefered_contact_email,'') ") execute:frappe.reload_doc("Payroll", "doctype", "salary_slip") -execute:frappe.db.sql("update `tabSalary Slip` set posting_date=creation") -execute:frappe.reload_doc("stock", "doctype", "stock_settings") -erpnext.patches.v8_0.create_domain_docs #16-05-2017 -erpnext.patches.v7_1.update_portal_roles -erpnext.patches.v7_1.set_total_amount_currency_in_je -finally:erpnext.patches.v7_0.update_timesheet_communications -erpnext.patches.v7_0.update_status_of_zero_amount_sales_order -erpnext.patches.v7_1.add_field_for_task_dependent -erpnext.patches.v7_0.repost_bin_qty_and_item_projected_qty -erpnext.patches.v7_1.set_prefered_contact_email -execute:frappe.reload_doc('accounts', 'doctype', 'accounts_settings') -execute:frappe.db.set_value("Accounts Settings", "Accounts Settings", "unlink_payment_on_cancellation_of_invoice", 0) -execute:frappe.db.sql("update `tabStock Entry` set total_amount = 0 where purpose in('Repack', 'Manufacture')") -erpnext.patches.v7_1.save_stock_settings -erpnext.patches.v7_0.repost_gle_for_pi_with_update_stock #2016-11-01 -erpnext.patches.v7_1.add_account_user_role_for_timesheet -erpnext.patches.v7_0.set_base_amount_in_invoice_payment_table -erpnext.patches.v7_1.update_invoice_status -erpnext.patches.v7_0.po_status_issue_for_pr_return -erpnext.patches.v7_1.update_missing_salary_component_type -erpnext.patches.v7_1.rename_quality_inspection_field -erpnext.patches.v7_0.update_autoname_field -erpnext.patches.v7_1.update_bom_base_currency -erpnext.patches.v7_0.update_status_of_po_so -erpnext.patches.v7_1.set_budget_against_as_cost_center -erpnext.patches.v7_1.set_currency_exchange_date -erpnext.patches.v7_1.set_sales_person_status -erpnext.patches.v7_1.repost_stock_for_deleted_bins_for_merging_items -erpnext.patches.v7_2.update_website_for_variant -erpnext.patches.v7_2.update_assessment_modules -erpnext.patches.v7_2.update_doctype_status -erpnext.patches.v7_2.update_salary_slips -erpnext.patches.v7_2.delete_fleet_management_module_def -erpnext.patches.v7_2.contact_address_links -erpnext.patches.v7_2.mark_students_active -erpnext.patches.v7_2.set_null_value_to_fields -erpnext.patches.v7_2.update_guardian_name_in_student_master -erpnext.patches.v7_2.update_abbr_in_salary_slips -erpnext.patches.v7_2.rename_evaluation_criteria -erpnext.patches.v7_2.update_party_type -erpnext.patches.v7_2.setup_auto_close_settings -erpnext.patches.v7_2.empty_supplied_items_for_non_subcontracted -erpnext.patches.v7_2.arrear_leave_encashment_as_salary_component -erpnext.patches.v7_2.rename_att_date_attendance -erpnext.patches.v7_2.update_attendance_docstatus -erpnext.patches.v7_2.make_all_assessment_group -erpnext.patches.v8_0.repost_reserved_qty_for_multiple_sales_uom -erpnext.patches.v8_0.addresses_linked_to_lead -execute:frappe.delete_doc('DocType', 'Purchase Common') -erpnext.patches.v8_0.update_stock_qty_value_in_purchase_invoice -erpnext.patches.v8_0.update_supplier_address_in_stock_entry -erpnext.patches.v8_0.rename_is_sample_item_to_allow_zero_valuation_rate -erpnext.patches.v8_0.set_null_to_serial_nos_for_disabled_sales_invoices -erpnext.patches.v8_0.enable_booking_asset_depreciation_automatically -erpnext.patches.v8_0.set_project_copied_from -erpnext.patches.v8_0.update_status_as_paid_for_completed_expense_claim -erpnext.patches.v7_2.stock_uom_in_selling -erpnext.patches.v8_0.revert_manufacturers_table_from_item -erpnext.patches.v8_0.disable_instructor_role -erpnext.patches.v8_0.merge_student_batch_and_student_group -erpnext.patches.v8_0.rename_total_margin_to_rate_with_margin # 11-05-2017 -erpnext.patches.v8_0.fix_status_for_invoices_with_negative_outstanding -erpnext.patches.v8_0.make_payments_table_blank_for_non_pos_invoice -erpnext.patches.v8_0.set_sales_invoice_serial_number_from_delivery_note -erpnext.patches.v8_0.delete_schools_depricated_doctypes -erpnext.patches.v8_0.update_customer_pos_id -erpnext.patches.v8_0.rename_items_in_status_field_of_material_request -erpnext.patches.v8_0.delete_bin_indexes -erpnext.patches.v8_0.move_account_head_from_account_to_warehouse_for_inventory -erpnext.patches.v8_0.change_in_words_varchar_length -erpnext.patches.v8_0.update_stock_qty_value_in_bom_item -erpnext.patches.v8_0.update_sales_cost_in_project -erpnext.patches.v8_0.save_system_settings -erpnext.patches.v8_1.delete_deprecated_reports -erpnext.patches.v9_0.remove_subscription_module -erpnext.patches.v8_7.make_subscription_from_recurring_data erpnext.patches.v8_1.setup_gst_india #2017-06-27 -execute:frappe.reload_doc('regional', 'doctype', 'gst_hsn_code') erpnext.patches.v8_1.removed_roles_from_gst_report_non_indian_account #16-08-2018 -erpnext.patches.v8_1.gst_fixes #2017-07-06 -erpnext.patches.v8_0.update_production_orders -erpnext.patches.v8_1.remove_sales_invoice_from_returned_serial_no -erpnext.patches.v8_1.allow_invoice_copy_to_edit_after_submit -erpnext.patches.v8_1.add_hsn_sac_codes -erpnext.patches.v8_1.update_gst_state #17-07-2017 -erpnext.patches.v8_1.removed_report_support_hours -erpnext.patches.v8_1.add_indexes_in_transaction_doctypes -erpnext.patches.v8_3.set_restrict_to_domain_for_module_def -erpnext.patches.v8_1.update_expense_claim_status -erpnext.patches.v8_3.update_company_total_sales #2017-08-16 -erpnext.patches.v8_4.make_scorecard_records -erpnext.patches.v8_1.set_delivery_date_in_so_item #2017-07-28 -erpnext.patches.v8_5.fix_tax_breakup_for_non_invoice_docs -erpnext.patches.v8_5.remove_quotations_route_in_sidebar -erpnext.patches.v8_5.update_existing_data_in_project_type -erpnext.patches.v8_5.set_default_mode_of_payment -erpnext.patches.v8_5.update_customer_group_in_POS_profile -erpnext.patches.v8_6.update_timesheet_company_from_PO -erpnext.patches.v8_6.set_write_permission_for_quotation_for_sales_manager -erpnext.patches.v8_5.remove_project_type_property_setter erpnext.patches.v8_7.sync_india_custom_fields -erpnext.patches.v8_7.fix_purchase_receipt_status -erpnext.patches.v8_6.rename_bom_update_tool -erpnext.patches.v8_9.add_setup_progress_actions #08-09-2017 #26-09-2017 #22-11-2017 #15-12-2017 -erpnext.patches.v8_9.rename_company_sales_target_field -erpnext.patches.v8_8.set_bom_rate_as_per_uom -erpnext.patches.v8_8.add_new_fields_in_accounts_settings -erpnext.patches.v8_9.set_default_customer_group -erpnext.patches.v8_9.delete_gst_doctypes_for_outside_india_accounts -erpnext.patches.v8_9.set_default_fields_in_variant_settings -erpnext.patches.v8_9.update_billing_gstin_for_indian_account -erpnext.patches.v8_9.set_member_party_type -erpnext.patches.v9_0.add_user_to_child_table_in_pos_profile -erpnext.patches.v9_0.set_schedule_date_for_material_request_and_purchase_order -erpnext.patches.v9_0.student_admission_childtable_migrate -erpnext.patches.v9_0.add_healthcare_domain -erpnext.patches.v9_0.set_variant_item_description -erpnext.patches.v9_0.set_uoms_in_variant_field -erpnext.patches.v9_0.copy_old_fees_field_data -execute:frappe.delete_doc_if_exists("DocType", "Program Fee") -erpnext.patches.v9_0.set_pos_profile_name -erpnext.patches.v9_0.remove_non_existing_warehouse_from_stock_settings -execute:frappe.delete_doc_if_exists("DocType", "Program Fee") -erpnext.patches.v8_10.change_default_customer_credit_days -erpnext.patches.v9_0.update_employee_loan_details -erpnext.patches.v9_2.delete_healthcare_domain_default_items -erpnext.patches.v9_1.create_issue_opportunity_type -erpnext.patches.v9_2.rename_translated_domains_in_en -erpnext.patches.v9_0.set_shipping_type_for_existing_shipping_rules -erpnext.patches.v9_0.update_multi_uom_fields_in_material_request -erpnext.patches.v9_2.repost_reserved_qty_for_production -erpnext.patches.v9_2.remove_company_from_patient -erpnext.patches.v9_2.set_item_name_in_production_order -erpnext.patches.v10_0.update_lft_rgt_for_employee -erpnext.patches.v9_2.rename_net_weight_in_item_master -erpnext.patches.v9_2.delete_process_payroll -erpnext.patches.v10_0.add_agriculture_domain -erpnext.patches.v10_0.add_non_profit_domain -erpnext.patches.v10_0.setup_vat_for_uae_and_saudi_arabia #2017-12-28 -erpnext.patches.v10_0.set_primary_contact_for_customer -erpnext.patches.v10_0.copy_projects_renamed_fields -erpnext.patches.v10_0.enabled_regional_print_format_based_on_country -erpnext.patches.v10_0.update_asset_calculate_depreciation -erpnext.patches.v10_0.add_guardian_role_for_parent_portal -erpnext.patches.v10_0.set_numeric_ranges_in_template_if_blank -erpnext.patches.v10_0.update_reserved_qty_for_purchase_order erpnext.patches.v10_0.fichier_des_ecritures_comptables_for_france -erpnext.patches.v10_0.update_assessment_plan -erpnext.patches.v10_0.update_assessment_result -erpnext.patches.v10_0.set_default_payment_terms_based_on_company -erpnext.patches.v10_0.update_sales_order_link_to_purchase_order erpnext.patches.v10_0.rename_price_to_rate_in_pricing_rule erpnext.patches.v10_0.set_currency_in_pricing_rule -erpnext.patches.v10_0.set_b2c_limit erpnext.patches.v10_0.update_translatable_fields erpnext.patches.v10_0.rename_offer_letter_to_job_offer execute:frappe.delete_doc('DocType', 'Production Planning Tool', ignore_missing=True) @@ -496,16 +21,6 @@ erpnext.patches.v10_0.migrate_daily_work_summary_settings_to_daily_work_summary_ erpnext.patches.v10_0.add_default_cash_flow_mappers erpnext.patches.v11_0.rename_duplicate_item_code_values erpnext.patches.v11_0.make_quality_inspection_template -erpnext.patches.v10_0.update_status_for_multiple_source_in_po -erpnext.patches.v10_0.set_auto_created_serial_no_in_stock_entry -erpnext.patches.v10_0.update_territory_and_customer_group -erpnext.patches.v10_0.update_warehouse_address_details -erpnext.patches.v10_0.update_reserved_qty_for_purchase_order -erpnext.patches.v10_0.update_hub_connector_domain -erpnext.patches.v10_0.set_student_party_type -erpnext.patches.v10_0.update_project_in_sle -erpnext.patches.v10_0.fix_reserved_qty_for_sub_contract -erpnext.patches.v10_0.repost_requested_qty_for_non_stock_uom_items erpnext.patches.v11_0.merge_land_unit_with_location erpnext.patches.v11_0.add_index_on_nestedset_doctypes erpnext.patches.v11_0.remove_modules_setup_page @@ -514,7 +29,6 @@ erpnext.patches.v11_0.update_department_lft_rgt erpnext.patches.v11_0.add_default_email_template_for_leave erpnext.patches.v11_0.set_default_email_template_in_hr #08-06-2018 erpnext.patches.v11_0.uom_conversion_data #30-06-2018 -erpnext.patches.v10_0.taxes_issue_with_pos erpnext.patches.v11_0.update_account_type_in_party_type erpnext.patches.v11_0.rename_healthcare_doctype_and_fields erpnext.patches.v11_0.rename_supplier_type_to_supplier_group @@ -522,8 +36,6 @@ erpnext.patches.v10_1.transfer_subscription_to_auto_repeat erpnext.patches.v11_0.update_brand_in_item_price erpnext.patches.v11_0.create_default_success_action erpnext.patches.v11_0.add_healthcare_service_unit_tree_root -erpnext.patches.v10_0.set_qty_in_transactions_based_on_serial_no_input -erpnext.patches.v10_0.show_leaves_of_all_department_members_in_calendar erpnext.patches.v11_0.rename_field_max_days_allowed erpnext.patches.v11_0.create_salary_structure_assignments erpnext.patches.v11_0.rename_health_insurance @@ -536,7 +48,6 @@ erpnext.patches.v11_0.move_item_defaults_to_child_table_for_multicompany #02-07- erpnext.patches.v11_0.refactor_erpnext_shopify #2018-09-07 erpnext.patches.v11_0.rename_overproduction_percent_field erpnext.patches.v11_0.update_backflush_subcontract_rm_based_on_bom -erpnext.patches.v10_0.update_status_in_purchase_receipt erpnext.patches.v11_0.inter_state_field_for_gst erpnext.patches.v11_0.rename_members_with_naming_series #04-06-2018 erpnext.patches.v11_0.set_update_field_and_value_in_workflow_state @@ -550,13 +61,10 @@ erpnext.patches.v11_0.skip_user_permission_check_for_department erpnext.patches.v11_0.set_department_for_doctypes erpnext.patches.v11_0.update_allow_transfer_for_manufacture erpnext.patches.v11_0.add_item_group_defaults -erpnext.patches.v10_0.update_address_template_for_india erpnext.patches.v11_0.add_expense_claim_default_account execute:frappe.delete_doc("Page", "hub") erpnext.patches.v11_0.reset_publish_in_hub_for_all_items erpnext.patches.v11_0.update_hub_url # 2018-08-31 # 2018-09-03 -erpnext.patches.v10_0.set_discount_amount -erpnext.patches.v10_0.recalculate_gross_margin_for_project erpnext.patches.v11_0.make_job_card erpnext.patches.v11_0.redesign_healthcare_billing_work_flow erpnext.patches.v10_0.delete_hub_documents # 12-08-2018 @@ -570,9 +78,6 @@ execute:frappe.delete_doc_if_exists("Page", "stock-analytics") execute:frappe.delete_doc_if_exists("Page", "production-analytics") erpnext.patches.v11_0.ewaybill_fields_gst_india #2018-11-13 #2019-01-09 #2019-04-01 #2019-04-26 #2019-05-03 erpnext.patches.v11_0.drop_column_max_days_allowed -erpnext.patches.v10_0.update_user_image_in_employee -erpnext.patches.v10_0.repost_gle_for_purchase_receipts_with_rejected_items -erpnext.patches.v10_0.allow_operators_in_supplier_scorecard erpnext.patches.v10_0.item_barcode_childtable_migrate # 16-02-2019 erpnext.patches.v11_0.update_delivery_trip_status erpnext.patches.v11_0.set_missing_gst_hsn_code From c68006b6078028d33b3872cc9569043f1d73bfad Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Thu, 3 Jun 2021 20:05:00 +0530 Subject: [PATCH 110/135] ci: Update ERPNext backup patch test >= v10 * Generated v10 backup archive * used old v7 erpnext backup hosted via build.erpnext.com * upgraded to v10 frappe + erpnext * Hosted backup on https://erpnext.com/files/v10-erpnext.sql.gz --- .github/workflows/patch.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/patch.yml b/.github/workflows/patch.yml index 7c9e0272c95..b96a3d6bbed 100644 --- a/.github/workflows/patch.yml +++ b/.github/workflows/patch.yml @@ -66,4 +66,8 @@ jobs: run: bash ${GITHUB_WORKSPACE}/.github/helper/install.sh - name: Run Patch Tests - run: cd ~/frappe-bench/ && wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz && bench --site test_site --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz && bench --site test_site migrate + run: | + cd ~/frappe-bench/ + wget https://erpnext.com/files/v10-erpnext.sql.gz + bench --site test_site --force restore ~/frappe-bench/v10-erpnext.sql.gz + bench --site test_site migrate From fb3ec7ccb8ade37c0180306fef57b2e491b9310d Mon Sep 17 00:00:00 2001 From: D Tim Cummings Date: Fri, 4 Jun 2021 16:28:45 +1000 Subject: [PATCH 111/135] fix: AttributeError: 'PurchaseReceiptItem' object has no attribute 'purchase_invoice' (#25902) * fix: AttributeError: 'PurchaseReceiptItem' object has no attribute 'purchase_invoice' This error occurs when upgrading from erpnext 13.0.1 to 13.4.0 after typing bench update --patch --reset * fix(minor): use .get instead of getattr --- erpnext/stock/doctype/purchase_receipt/purchase_receipt.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index f1292d8cbdd..83ba3244952 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -497,7 +497,7 @@ class PurchaseReceipt(BuyingController): def update_billing_status(self, update_modified=True): updated_pr = [self.name] for d in self.get("items"): - if d.purchase_invoice and d.purchase_invoice_item: + if d.get("purchase_invoice") and d.get("purchase_invoice_item"): d.db_set('billed_amt', d.amount, update_modified=update_modified) elif d.purchase_order_item: updated_pr += update_billed_amount_based_on_po(d.purchase_order_item, update_modified) @@ -748,4 +748,3 @@ def get_item_account_wise_additional_cost(purchase_document): account.base_amount * item.get(based_on_field) / total_item_cost return item_account_wise_cost - From e80902be8e3009777871bd0a3a6ad22decf994fa Mon Sep 17 00:00:00 2001 From: Sagar Vora Date: Fri, 28 May 2021 21:28:42 +0530 Subject: [PATCH 112/135] fix: choose correct Salary Structure Assignment when getting data for formula eval --- .../doctype/salary_slip/salary_slip.py | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/erpnext/payroll/doctype/salary_slip/salary_slip.py b/erpnext/payroll/doctype/salary_slip/salary_slip.py index 3c2533131b9..d1a76b38b99 100644 --- a/erpnext/payroll/doctype/salary_slip/salary_slip.py +++ b/erpnext/payroll/doctype/salary_slip/salary_slip.py @@ -493,8 +493,28 @@ class SalarySlip(TransactionBase): '''Returns data for evaluating formula''' data = frappe._dict() + salary_structure_assignment = frappe.get_value( + "Salary Structure Assignment", + { + "employee": self.employee, + "salary_structure": self.salary_structure, + "from_date": ("<=", self.start_date), + "docstatus": 1, + }, + order_by="from_date desc", + ) + + if not salary_structure_assignment: + frappe.throw( + _("Please assign a Salary Structure for Employee {0} " + "applicable from or before {1} first").format( + frappe.bold(self.employee_name), + frappe.bold(self.start_date) + ) + ) + data.update(frappe.get_doc("Salary Structure Assignment", - {"employee": self.employee, "salary_structure": self.salary_structure}).as_dict()) + salary_structure_assignment).as_dict()) data.update(frappe.get_doc("Employee", self.employee).as_dict()) data.update(self.as_dict()) From 5657fddb7ae948d0784d86f093392af84e375243 Mon Sep 17 00:00:00 2001 From: Sagar Vora Date: Sat, 29 May 2021 00:04:26 +0530 Subject: [PATCH 113/135] fix: improve filter for `from_date`; validation for joining and relieving date --- .../doctype/salary_slip/salary_slip.py | 40 +++++++++++++++---- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/erpnext/payroll/doctype/salary_slip/salary_slip.py b/erpnext/payroll/doctype/salary_slip/salary_slip.py index d1a76b38b99..f479f6be9e6 100644 --- a/erpnext/payroll/doctype/salary_slip/salary_slip.py +++ b/erpnext/payroll/doctype/salary_slip/salary_slip.py @@ -115,10 +115,23 @@ class SalarySlip(TransactionBase): status = "Cancelled" return status - def validate_dates(self): + def validate_dates(self, joining_date=None, relieving_date=None): if date_diff(self.end_date, self.start_date) < 0: frappe.throw(_("To date cannot be before From date")) + if not joining_date: + joining_date, relieving_date = frappe.get_cached_value( + "Employee", + self.employee, + ("date_of_joining", "relieving_date") + ) + + if date_diff(self.end_date, joining_date) < 0: + frappe.throw(_("Cannot create Salary Slip for Employee joining after Payroll Period")) + + if relieving_date and date_diff(relieving_date, self.start_date) < 0: + frappe.throw(_("Cannot create Salary Slip for Employee who has left before Payroll Period")) + def is_rounding_total_disabled(self): return cint(frappe.db.get_single_value("Payroll Settings", "disable_rounded_total")) @@ -154,9 +167,14 @@ class SalarySlip(TransactionBase): if not self.salary_slip_based_on_timesheet: self.get_date_details() - self.validate_dates() - joining_date, relieving_date = frappe.get_cached_value("Employee", self.employee, - ["date_of_joining", "relieving_date"]) + + joining_date, relieving_date = frappe.get_cached_value( + "Employee", + self.employee, + ("date_of_joining", "relieving_date") + ) + + self.validate_dates(joining_date, relieving_date) #getin leave details self.get_working_days_details(joining_date, relieving_date) @@ -492,13 +510,21 @@ class SalarySlip(TransactionBase): def get_data_for_eval(self): '''Returns data for evaluating formula''' data = frappe._dict() + employee = frappe.get_doc("Employee", self.employee).as_dict() + + start_date = getdate(self.start_date) + date_to_validate = ( + employee.date_of_joining + if employee.date_of_joining > start_date + else start_date + ) salary_structure_assignment = frappe.get_value( "Salary Structure Assignment", { "employee": self.employee, "salary_structure": self.salary_structure, - "from_date": ("<=", self.start_date), + "from_date": ("<=", date_to_validate), "docstatus": 1, }, order_by="from_date desc", @@ -509,14 +535,14 @@ class SalarySlip(TransactionBase): _("Please assign a Salary Structure for Employee {0} " "applicable from or before {1} first").format( frappe.bold(self.employee_name), - frappe.bold(self.start_date) + frappe.bold(formatdate(date_to_validate)), ) ) data.update(frappe.get_doc("Salary Structure Assignment", salary_structure_assignment).as_dict()) - data.update(frappe.get_doc("Employee", self.employee).as_dict()) + data.update(employee) data.update(self.as_dict()) # set values for components From bd92b4339cfef78f378ec23086c8e1371db72112 Mon Sep 17 00:00:00 2001 From: Sagar Vora Date: Fri, 4 Jun 2021 13:51:45 +0530 Subject: [PATCH 114/135] perf: use frappe.get_value with wildcard instead of another frappe.get_doc call --- erpnext/payroll/doctype/salary_slip/salary_slip.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/payroll/doctype/salary_slip/salary_slip.py b/erpnext/payroll/doctype/salary_slip/salary_slip.py index f479f6be9e6..c55bec89be8 100644 --- a/erpnext/payroll/doctype/salary_slip/salary_slip.py +++ b/erpnext/payroll/doctype/salary_slip/salary_slip.py @@ -527,7 +527,9 @@ class SalarySlip(TransactionBase): "from_date": ("<=", date_to_validate), "docstatus": 1, }, + "*", order_by="from_date desc", + as_dict=True, ) if not salary_structure_assignment: @@ -539,9 +541,7 @@ class SalarySlip(TransactionBase): ) ) - data.update(frappe.get_doc("Salary Structure Assignment", - salary_structure_assignment).as_dict()) - + data.update(salary_structure_assignment) data.update(employee) data.update(self.as_dict()) From 0b7da52ef17f192b72b5c034b0704dd7c2b061b4 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Fri, 4 Jun 2021 17:07:45 +0530 Subject: [PATCH 115/135] fix(patch): Handle NULL values from fieldtype change --- erpnext/patches/v11_0/rename_bom_wo_fields.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/erpnext/patches/v11_0/rename_bom_wo_fields.py b/erpnext/patches/v11_0/rename_bom_wo_fields.py index b4a740fabbf..882ec84e644 100644 --- a/erpnext/patches/v11_0/rename_bom_wo_fields.py +++ b/erpnext/patches/v11_0/rename_bom_wo_fields.py @@ -6,6 +6,10 @@ import frappe from frappe.model.utils.rename_field import rename_field def execute(): + # updating column value to handle field change from Data to Currency + changed_field = "base_scrap_material_cost" + frappe.db.sql(f"update `tabBOM` set {changed_field} = '0' where trim(coalesce({changed_field}, ''))= ''") + for doctype in ['BOM Explosion Item', 'BOM Item', 'Work Order Item', 'Item']: if frappe.db.has_column(doctype, 'allow_transfer_for_manufacture'): if doctype != 'Item': From 4e2e8daca9bb9ece93acde85df38a69304fb43a2 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Fri, 4 Jun 2021 17:56:28 +0530 Subject: [PATCH 116/135] fix(patch): Reload linked doctypes before renaming dt --- .../v13_0/healthcare_lab_module_rename_doctypes.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/erpnext/patches/v13_0/healthcare_lab_module_rename_doctypes.py b/erpnext/patches/v13_0/healthcare_lab_module_rename_doctypes.py index 9af0a8dbef7..dcfbc3834d5 100644 --- a/erpnext/patches/v13_0/healthcare_lab_module_rename_doctypes.py +++ b/erpnext/patches/v13_0/healthcare_lab_module_rename_doctypes.py @@ -1,6 +1,7 @@ from __future__ import unicode_literals import frappe from frappe.model.utils.rename_field import rename_field +from frappe.model.rename_doc import get_link_fields def execute(): if frappe.db.exists('DocType', 'Lab Test') and frappe.db.exists('DocType', 'Lab Test Template'): @@ -17,9 +18,18 @@ def execute(): frappe.reload_doc('healthcare', 'doctype', 'lab_test_template') for old_dt, new_dt in doctypes.items(): - if not frappe.db.table_exists(new_dt) and frappe.db.table_exists(old_dt): + should_rename = ( + frappe.db.table_exists(old_dt) + and not frappe.db.table_exists(new_dt) + ) + if should_rename: frappe.reload_doc('healthcare', 'doctype', frappe.scrub(old_dt)) + + linked_doctypes = {x.parent for x in get_link_fields(old_dt)} + for linked_doctype in linked_doctypes: + frappe.reload_doctype(linked_doctype, force=True) frappe.rename_doc('DocType', old_dt, new_dt, force=True) + frappe.reload_doc('healthcare', 'doctype', frappe.scrub(new_dt)) frappe.delete_doc_if_exists('DocType', old_dt) From ac99c719bcb901b622f2b5ceb2ebf9df5a285616 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Fri, 4 Jun 2021 20:10:26 +0530 Subject: [PATCH 117/135] Revert "fix(patch): Reload linked doctypes before renaming dt" This reverts commit 4e2e8daca9bb9ece93acde85df38a69304fb43a2 because although it fixed it locally, didn't seem to do anything for erpnext CI --- .../v13_0/healthcare_lab_module_rename_doctypes.py | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/erpnext/patches/v13_0/healthcare_lab_module_rename_doctypes.py b/erpnext/patches/v13_0/healthcare_lab_module_rename_doctypes.py index dcfbc3834d5..9af0a8dbef7 100644 --- a/erpnext/patches/v13_0/healthcare_lab_module_rename_doctypes.py +++ b/erpnext/patches/v13_0/healthcare_lab_module_rename_doctypes.py @@ -1,7 +1,6 @@ from __future__ import unicode_literals import frappe from frappe.model.utils.rename_field import rename_field -from frappe.model.rename_doc import get_link_fields def execute(): if frappe.db.exists('DocType', 'Lab Test') and frappe.db.exists('DocType', 'Lab Test Template'): @@ -18,18 +17,9 @@ def execute(): frappe.reload_doc('healthcare', 'doctype', 'lab_test_template') for old_dt, new_dt in doctypes.items(): - should_rename = ( - frappe.db.table_exists(old_dt) - and not frappe.db.table_exists(new_dt) - ) - if should_rename: + if not frappe.db.table_exists(new_dt) and frappe.db.table_exists(old_dt): frappe.reload_doc('healthcare', 'doctype', frappe.scrub(old_dt)) - - linked_doctypes = {x.parent for x in get_link_fields(old_dt)} - for linked_doctype in linked_doctypes: - frappe.reload_doctype(linked_doctype, force=True) frappe.rename_doc('DocType', old_dt, new_dt, force=True) - frappe.reload_doc('healthcare', 'doctype', frappe.scrub(new_dt)) frappe.delete_doc_if_exists('DocType', old_dt) From 102afe7de1638b83fa906ad88746c9ca2bf4e58a Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Fri, 4 Jun 2021 20:11:34 +0530 Subject: [PATCH 118/135] fix: Manually link_fields from flags before rename_doc --- .../v13_0/healthcare_lab_module_rename_doctypes.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/erpnext/patches/v13_0/healthcare_lab_module_rename_doctypes.py b/erpnext/patches/v13_0/healthcare_lab_module_rename_doctypes.py index 9af0a8dbef7..2549a1e91ee 100644 --- a/erpnext/patches/v13_0/healthcare_lab_module_rename_doctypes.py +++ b/erpnext/patches/v13_0/healthcare_lab_module_rename_doctypes.py @@ -2,6 +2,7 @@ from __future__ import unicode_literals import frappe from frappe.model.utils.rename_field import rename_field + def execute(): if frappe.db.exists('DocType', 'Lab Test') and frappe.db.exists('DocType', 'Lab Test Template'): # rename child doctypes @@ -17,7 +18,12 @@ def execute(): frappe.reload_doc('healthcare', 'doctype', 'lab_test_template') for old_dt, new_dt in doctypes.items(): - if not frappe.db.table_exists(new_dt) and frappe.db.table_exists(old_dt): + frappe.flags.link_fields = {} + should_rename = ( + frappe.db.table_exists(old_dt) + and not frappe.db.table_exists(new_dt) + ) + if should_rename: frappe.reload_doc('healthcare', 'doctype', frappe.scrub(old_dt)) frappe.rename_doc('DocType', old_dt, new_dt, force=True) frappe.reload_doc('healthcare', 'doctype', frappe.scrub(new_dt)) From bf0528413d7336b6e55aad70f0cfed12ee0db9fa Mon Sep 17 00:00:00 2001 From: Anupam Date: Sun, 6 Jun 2021 13:12:13 +0530 Subject: [PATCH 119/135] fix: payroll entry employee detail issue --- erpnext/payroll/doctype/payroll_entry/payroll_entry.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/payroll/doctype/payroll_entry/payroll_entry.py b/erpnext/payroll/doctype/payroll_entry/payroll_entry.py index 3953b463f12..67893448ba4 100644 --- a/erpnext/payroll/doctype/payroll_entry/payroll_entry.py +++ b/erpnext/payroll/doctype/payroll_entry/payroll_entry.py @@ -673,7 +673,7 @@ def employee_query(doctype, txt, searchfield, start, page_len, filters): include_employees = [] emp_cond = '' if filters.start_date and filters.end_date: - employee_list = get_employee_list(filters) + employee_list = get_employee_list(filters) or [] emp = filters.get('employees') include_employees = [employee.employee for employee in employee_list if employee.employee not in emp] filters.pop('start_date') From 7f5378d98ac3bee8175d972fda5cc6e958fe23e2 Mon Sep 17 00:00:00 2001 From: Sagar Vora Date: Mon, 7 Jun 2021 18:40:54 +0530 Subject: [PATCH 120/135] fix: tests --- .../doctype/salary_slip/test_salary_slip.py | 51 +++++++++++-------- .../salary_structure/test_salary_structure.py | 39 +++++++++----- 2 files changed, 57 insertions(+), 33 deletions(-) diff --git a/erpnext/payroll/doctype/salary_slip/test_salary_slip.py b/erpnext/payroll/doctype/salary_slip/test_salary_slip.py index 01e4170d311..9e7db977ab1 100644 --- a/erpnext/payroll/doctype/salary_slip/test_salary_slip.py +++ b/erpnext/payroll/doctype/salary_slip/test_salary_slip.py @@ -8,7 +8,6 @@ import erpnext import calendar import random from erpnext.accounts.utils import get_fiscal_year -from frappe.utils.make_random import get_random from frappe.utils import getdate, nowdate, add_days, add_months, flt, get_first_day, get_last_day, cstr from erpnext.payroll.doctype.salary_structure.salary_structure import make_salary_slip from erpnext.payroll.doctype.payroll_entry.payroll_entry import get_month_details @@ -155,12 +154,14 @@ class TestSalarySlip(unittest.TestCase): self.assertEqual(ss.gross_pay, 78000) def test_payment_days(self): + from erpnext.payroll.doctype.salary_structure.test_salary_structure import create_salary_structure_assignment + no_of_days = self.get_no_of_days() # Holidays not included in working days frappe.db.set_value("Payroll Settings", None, "include_holidays_in_total_working_days", 1) # set joinng date in the same month - make_employee("test_payment_days@salary.com") + employee = make_employee("test_payment_days@salary.com") if getdate(nowdate()).day >= 15: relieving_date = getdate(add_days(nowdate(),-10)) date_of_joining = getdate(add_days(nowdate(),-10)) @@ -174,25 +175,30 @@ class TestSalarySlip(unittest.TestCase): date_of_joining = getdate(nowdate()) relieving_date = getdate(nowdate()) - frappe.db.set_value("Employee", frappe.get_value("Employee", - {"employee_name":"test_payment_days@salary.com"}, "name"), "date_of_joining", date_of_joining) - frappe.db.set_value("Employee", frappe.get_value("Employee", - {"employee_name":"test_payment_days@salary.com"}, "name"), "relieving_date", None) - frappe.db.set_value("Employee", frappe.get_value("Employee", - {"employee_name":"test_payment_days@salary.com"}, "name"), "status", "Active") + frappe.db.set_value("Employee", employee, { + "date_of_joining": date_of_joining, + "relieving_date": None, + "status": "Active" + }) - ss = make_employee_salary_slip("test_payment_days@salary.com", "Monthly", "Test Payment Days") + salary_structure = "Test Payment Days" + ss = make_employee_salary_slip("test_payment_days@salary.com", "Monthly", salary_structure) self.assertEqual(ss.total_working_days, no_of_days[0]) self.assertEqual(ss.payment_days, (no_of_days[0] - getdate(date_of_joining).day + 1)) # set relieving date in the same month - frappe.db.set_value("Employee",frappe.get_value("Employee", - {"employee_name":"test_payment_days@salary.com"}, "name"), "date_of_joining", (add_days(nowdate(),-60))) - frappe.db.set_value("Employee", frappe.get_value("Employee", - {"employee_name":"test_payment_days@salary.com"}, "name"), "relieving_date", relieving_date) - frappe.db.set_value("Employee", frappe.get_value("Employee", - {"employee_name":"test_payment_days@salary.com"}, "name"), "status", "Left") + frappe.db.set_value("Employee", employee, { + "date_of_joining": add_days(nowdate(),-60), + "relieving_date": relieving_date, + "status": "Left" + }) + + if date_of_joining.day > 1: + self.assertRaises(frappe.ValidationError, ss.save) + + create_salary_structure_assignment(employee, salary_structure) + ss.reload() ss.save() self.assertEqual(ss.total_working_days, no_of_days[0]) @@ -285,6 +291,7 @@ class TestSalarySlip(unittest.TestCase): def test_multi_currency_salary_slip(self): from erpnext.payroll.doctype.salary_structure.test_salary_structure import make_salary_structure + applicant = make_employee("test_multi_currency_salary_slip@salary.com", company="_Test Company") frappe.db.sql("""delete from `tabSalary Structure` where name='Test Multi Currency Salary Slip'""") salary_structure = make_salary_structure("Test Multi Currency Salary Slip", "Monthly", employee=applicant, company="_Test Company", currency='USD') @@ -325,7 +332,8 @@ class TestSalarySlip(unittest.TestCase): def test_component_wise_year_to_date_computation(self): from erpnext.payroll.doctype.salary_structure.test_salary_structure import make_salary_structure - applicant = make_employee("test_ytd@salary.com", company="_Test Company") + employee_name = "test_component_wise_ytd@salary.com" + applicant = make_employee(employee_name, company="_Test Company") payroll_period = create_payroll_period(name="_Test Payroll Period 1", company="_Test Company") @@ -336,13 +344,13 @@ class TestSalarySlip(unittest.TestCase): "Monthly", employee=applicant, company="_Test Company", currency="INR", payroll_period=payroll_period) # clear salary slip for this employee - frappe.db.sql("DELETE FROM `tabSalary Slip` where employee_name = 'test_ytd@salary.com'") + frappe.db.sql("DELETE FROM `tabSalary Slip` where employee_name = '%s'" % employee_name) create_salary_slips_for_payroll_period(applicant, salary_structure.name, payroll_period, deduct_random=False, num=3) salary_slips = frappe.get_all("Salary Slip", fields=["name"], filters={"employee_name": - "test_ytd@salary.com"}, order_by = "posting_date") + employee_name}, order_by="posting_date") year_to_date = dict() for slip in salary_slips: @@ -380,10 +388,10 @@ class TestSalarySlip(unittest.TestCase): from erpnext.payroll.doctype.salary_structure.test_salary_structure import \ make_salary_structure, create_salary_structure_assignment + salary_structure = make_salary_structure("Stucture to test tax", "Monthly", - other_details={"max_benefits": 100000}, test_tax=True) - create_salary_structure_assignment(employee, salary_structure.name, - payroll_period.start_date) + other_details={"max_benefits": 100000}, test_tax=True, + employee=employee, payroll_period=payroll_period) # create salary slip for whole period deducting tax only on last period # to find the total tax amount paid @@ -469,6 +477,7 @@ class TestSalarySlip(unittest.TestCase): def make_employee_salary_slip(user, payroll_frequency, salary_structure=None): from erpnext.payroll.doctype.salary_structure.test_salary_structure import make_salary_structure + if not salary_structure: salary_structure = payroll_frequency + " Salary Structure Test for Salary Slip" diff --git a/erpnext/payroll/doctype/salary_structure/test_salary_structure.py b/erpnext/payroll/doctype/salary_structure/test_salary_structure.py index 36387f23df0..26cd9922e46 100644 --- a/erpnext/payroll/doctype/salary_structure/test_salary_structure.py +++ b/erpnext/payroll/doctype/salary_structure/test_salary_structure.py @@ -6,7 +6,7 @@ import frappe import unittest import erpnext from frappe.utils.make_random import get_random -from frappe.utils import nowdate, add_days, add_years, getdate, add_months +from frappe.utils import nowdate, add_days, add_years, getdate, add_months, get_first_day, date_diff from erpnext.payroll.doctype.salary_structure.salary_structure import make_salary_slip from erpnext.payroll.doctype.salary_slip.test_salary_slip import make_earning_salary_component,\ make_deduction_salary_component, make_employee_salary_slip, create_tax_slab @@ -113,8 +113,9 @@ class TestSalaryStructure(unittest.TestCase): sal_struct = make_salary_structure("Salary Structure Multi Currency", "Monthly", currency='USD') self.assertEqual(sal_struct.currency, 'USD') -def make_salary_structure(salary_structure, payroll_frequency, employee=None, dont_submit=False, other_details=None, - test_tax=False, company=None, currency=erpnext.get_default_currency(), payroll_period=None): +def make_salary_structure(salary_structure, payroll_frequency, employee=None, + from_date=None, dont_submit=False, other_details=None,test_tax=False, + company=None, currency=erpnext.get_default_currency(), payroll_period=None): if test_tax: frappe.db.sql("""delete from `tabSalary Structure` where name=%s""",(salary_structure)) @@ -139,10 +140,23 @@ def make_salary_structure(salary_structure, payroll_frequency, employee=None, do else: salary_structure_doc = frappe.get_doc("Salary Structure", salary_structure) + filters = {'employee':employee, 'docstatus': 1} + if not from_date and payroll_period: + from_date = payroll_period.start_date + + if from_date: + filters['from_date'] = from_date + if employee and not frappe.db.get_value("Salary Structure Assignment", - {'employee':employee, 'docstatus': 1}) and salary_structure_doc.docstatus==1: - create_salary_structure_assignment(employee, salary_structure, company=company, currency=currency, - payroll_period=payroll_period) + filters) and salary_structure_doc.docstatus==1: + create_salary_structure_assignment( + employee, + salary_structure, + from_date=from_date, + company=company, + currency=currency, + payroll_period=payroll_period + ) return salary_structure_doc @@ -165,12 +179,13 @@ def create_salary_structure_assignment(employee, salary_structure, from_date=Non salary_structure_assignment.base = 50000 salary_structure_assignment.variable = 5000 - if getdate(nowdate()).day == 1: - date = from_date or nowdate() - else: - date = from_date or add_days(nowdate(), -1) + if not from_date: + from_date = get_first_day(nowdate()) + joining_date = frappe.get_cached_value("Employee", employee, "date_of_joining") + if date_diff(joining_date, from_date) > 0: + from_date = joining_date - salary_structure_assignment.from_date = date + salary_structure_assignment.from_date = from_date salary_structure_assignment.salary_structure = salary_structure salary_structure_assignment.currency = currency salary_structure_assignment.payroll_payable_account = get_payable_account(company) @@ -183,4 +198,4 @@ def create_salary_structure_assignment(employee, salary_structure, from_date=Non def get_payable_account(company=None): if not company: company = erpnext.get_default_company() - return frappe.db.get_value("Company", company, "default_payroll_payable_account") \ No newline at end of file + return frappe.db.get_value("Company", company, "default_payroll_payable_account") From 5b1e7a61b88e354038db2a2dd74edba55d5d92a0 Mon Sep 17 00:00:00 2001 From: Sagar Vora Date: Mon, 7 Jun 2021 19:34:02 +0530 Subject: [PATCH 121/135] test: remove unused imports --- .../payroll/doctype/salary_structure/test_salary_structure.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/payroll/doctype/salary_structure/test_salary_structure.py b/erpnext/payroll/doctype/salary_structure/test_salary_structure.py index 26cd9922e46..dce6b7aa3d4 100644 --- a/erpnext/payroll/doctype/salary_structure/test_salary_structure.py +++ b/erpnext/payroll/doctype/salary_structure/test_salary_structure.py @@ -6,7 +6,7 @@ import frappe import unittest import erpnext from frappe.utils.make_random import get_random -from frappe.utils import nowdate, add_days, add_years, getdate, add_months, get_first_day, date_diff +from frappe.utils import nowdate, add_years, get_first_day, date_diff from erpnext.payroll.doctype.salary_structure.salary_structure import make_salary_slip from erpnext.payroll.doctype.salary_slip.test_salary_slip import make_earning_salary_component,\ make_deduction_salary_component, make_employee_salary_slip, create_tax_slab From 646f0c3b53239f05ad39c8eaecdfcccaca5bd564 Mon Sep 17 00:00:00 2001 From: walstanb Date: Tue, 8 Jun 2021 17:54:34 +0530 Subject: [PATCH 122/135] fix: variable declaration --- erpnext/selling/doctype/quotation/quotation.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/erpnext/selling/doctype/quotation/quotation.js b/erpnext/selling/doctype/quotation/quotation.js index 7fecd4bc347..12234495493 100644 --- a/erpnext/selling/doctype/quotation/quotation.js +++ b/erpnext/selling/doctype/quotation/quotation.js @@ -53,8 +53,11 @@ erpnext.selling.QuotationController = class QuotationController extends erpnext. } refresh(doc, dt, dn) { super.refresh(doc, dt, dn); - doctype = doc.quotation_to == 'Customer' ? 'Customer':'Lead'; - frappe.dynamic_link = {doc: this.frm.doc, fieldname: 'party_name', doctype: doctype} + frappe.dynamic_link = { + doc: this.frm.doc, + fieldname: 'party_name', + doctype: doc.quotation_to == 'Customer' ? 'Customer' : 'Lead', + }; var me = this; From 6b8c123fd99dcc15f1b959a99573b5abb94419fe Mon Sep 17 00:00:00 2001 From: Jannat Patel <31363128+pateljannat@users.noreply.github.com> Date: Tue, 8 Jun 2021 18:57:49 +0530 Subject: [PATCH 123/135] fix: Quiz timer (#25983) * fix: quiz timer * fix: pass time bound parameter * fix: sider --- .../doctype/course_enrollment/course_enrollment.py | 2 +- erpnext/education/utils.py | 13 +++++++------ erpnext/public/js/education/lms/quiz.js | 8 +++----- erpnext/www/lms/content.html | 1 + 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/erpnext/education/doctype/course_enrollment/course_enrollment.py b/erpnext/education/doctype/course_enrollment/course_enrollment.py index 2b3acf1b93b..ce88990a70d 100644 --- a/erpnext/education/doctype/course_enrollment/course_enrollment.py +++ b/erpnext/education/doctype/course_enrollment/course_enrollment.py @@ -91,4 +91,4 @@ def check_activity_exists(enrollment, content_type, content): if activity: return activity[0].name else: - return None \ No newline at end of file + return None diff --git a/erpnext/education/utils.py b/erpnext/education/utils.py index 8f51fef8476..819106bde78 100644 --- a/erpnext/education/utils.py +++ b/erpnext/education/utils.py @@ -219,7 +219,6 @@ def get_quiz(quiz_name, course): try: quiz = frappe.get_doc("Quiz", quiz_name) questions = quiz.get_questions() - duration = quiz.duration except: frappe.throw(_("Quiz {0} does not exist").format(quiz_name), frappe.DoesNotExistError) return None @@ -236,15 +235,17 @@ def get_quiz(quiz_name, course): return { 'questions': questions, 'activity': None, - 'duration':duration + 'is_time_bound': quiz.is_time_bound, + 'duration':quiz.duration } student = get_current_student() course_enrollment = get_enrollment("course", course, student.name) status, score, result, time_taken = check_quiz_completion(quiz, course_enrollment) return { - 'questions': questions, + 'questions': questions, 'activity': {'is_complete': status, 'score': score, 'result': result, 'time_taken': time_taken}, + 'is_time_bound': quiz.is_time_bound, 'duration': quiz.duration } @@ -372,9 +373,9 @@ def check_content_completion(content_name, content_type, enrollment_name): def check_quiz_completion(quiz, enrollment_name): attempts = frappe.get_all("Quiz Activity", filters={ - 'enrollment': enrollment_name, + 'enrollment': enrollment_name, 'quiz': quiz.name - }, + }, fields=["name", "activity_date", "score", "status", "time_taken"] ) status = False if quiz.max_attempts == 0 else bool(len(attempts) >= quiz.max_attempts) @@ -389,4 +390,4 @@ def check_quiz_completion(quiz, enrollment_name): time_taken = attempts[0]['time_taken'] if result == 'Pass': status = True - return status, score, result, time_taken \ No newline at end of file + return status, score, result, time_taken diff --git a/erpnext/public/js/education/lms/quiz.js b/erpnext/public/js/education/lms/quiz.js index 5683f73d1b9..66160a7610c 100644 --- a/erpnext/public/js/education/lms/quiz.js +++ b/erpnext/public/js/education/lms/quiz.js @@ -20,10 +20,8 @@ class Quiz { } make(data) { - if (data.duration) { - const timer_display = document.createElement("div"); - timer_display.classList.add("lms-timer", "float-right", "font-weight-bold"); - document.getElementsByClassName("lms-title")[0].appendChild(timer_display); + if (data.is_time_bound) { + $(".lms-timer").removeClass("hide"); if (!data.activity || (data.activity && !data.activity.is_complete)) { this.initialiseTimer(data.duration); this.is_time_bound = true; @@ -237,4 +235,4 @@ class Question { this.options = option_list this.wrapper.appendChild(options_wrapper) } -} \ No newline at end of file +} diff --git a/erpnext/www/lms/content.html b/erpnext/www/lms/content.html index 15afb097b94..d22ef66d2a8 100644 --- a/erpnext/www/lms/content.html +++ b/erpnext/www/lms/content.html @@ -64,6 +64,7 @@

    {{ content.name }} ({{ position + 1 }}/{{length}})

    +
    {% endmacro %} From 8eab59b06240d27dea1ea443a21bf285b1e53de2 Mon Sep 17 00:00:00 2001 From: ChillarAnand Date: Wed, 9 Jun 2021 18:05:39 +0530 Subject: [PATCH 124/135] chore: Upgrade PyGithub to 1.55 Frappe has upgraded to PyJWT>2. Upgrading PyGithub to resolve dependency issues --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index e30746a5380..f28906ae352 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,7 +5,7 @@ googlemaps # used in ERPNext, but dependency is defined in Frappe pandas~=1.1.5 plaid-python~=7.2.1 pycountry~=20.7.3 -PyGithub~=1.54.1 +PyGithub~=1.55 python-stdnum~=1.16 python-youtube~=0.8.0 taxjar~=1.9.2 From 8f5ae0470df5270a2384ffdc1b4e376840d591ce Mon Sep 17 00:00:00 2001 From: walstanb Date: Thu, 10 Jun 2021 16:35:27 +0530 Subject: [PATCH 125/135] fix: syntax error in stock entry --- erpnext/stock/doctype/stock_entry/stock_entry.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js index 786285ae4fe..9c4f0ddcbc9 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.js +++ b/erpnext/stock/doctype/stock_entry/stock_entry.js @@ -984,7 +984,7 @@ erpnext.stock.StockEntry = class StockEntry extends erpnext.stock.StockControlle if(!row.t_warehouse) row.t_warehouse = this.frm.doc.to_warehouse; } - from_warehouse: function(doc) { + from_warehouse(doc) { this.frm.trigger('set_transit_warehouse'); this.set_warehouse_in_children(doc.items, "s_warehouse", doc.from_warehouse); } From 48f2839079639aa279adb5106398ab9a1224101f Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Thu, 10 Jun 2021 18:09:49 +0530 Subject: [PATCH 126/135] fix: Sort account balances by account name --- .../report/account_balance/account_balance.py | 4 +--- .../account_balance/test_account_balance.py | 22 +++++++++---------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/erpnext/accounts/report/account_balance/account_balance.py b/erpnext/accounts/report/account_balance/account_balance.py index 65e7d789bb0..be64c327fdf 100644 --- a/erpnext/accounts/report/account_balance/account_balance.py +++ b/erpnext/accounts/report/account_balance/account_balance.py @@ -58,11 +58,9 @@ def get_conditions(filters): def get_data(filters): data = [] - conditions = get_conditions(filters) - accounts = frappe.db.get_all("Account", fields=["name", "account_currency"], - filters=conditions) + filters=conditions, order_by='name') for d in accounts: balance = get_balance_on(d.name, date=filters.report_date) diff --git a/erpnext/accounts/report/account_balance/test_account_balance.py b/erpnext/accounts/report/account_balance/test_account_balance.py index b6ced312d09..14ddf4a30fc 100644 --- a/erpnext/accounts/report/account_balance/test_account_balance.py +++ b/erpnext/accounts/report/account_balance/test_account_balance.py @@ -23,7 +23,7 @@ class TestAccountBalance(unittest.TestCase): expected_data = [ { - "account": 'Sales - _TC2', + "account": 'Direct Income - _TC2', "currency": 'EUR', "balance": -100.0, }, @@ -32,21 +32,21 @@ class TestAccountBalance(unittest.TestCase): "currency": 'EUR', "balance": -100.0, }, - { - "account": 'Service - _TC2', - "currency": 'EUR', - "balance": 0.0, - }, - { - "account": 'Direct Income - _TC2', - "currency": 'EUR', - "balance": -100.0, - }, { "account": 'Indirect Income - _TC2', "currency": 'EUR', "balance": 0.0, }, + { + "account": 'Sales - _TC2', + "currency": 'EUR', + "balance": -100.0, + }, + { + "account": 'Service - _TC2', + "currency": 'EUR', + "balance": 0.0, + } ] self.assertEqual(expected_data, report[1]) From 32ebb1001e0eaff0110e5785f4c0fdbde6794c77 Mon Sep 17 00:00:00 2001 From: Anupam Date: Thu, 10 Jun 2021 19:32:00 +0530 Subject: [PATCH 127/135] fix: review chnages --- erpnext/payroll/doctype/payroll_entry/payroll_entry.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/payroll/doctype/payroll_entry/payroll_entry.py b/erpnext/payroll/doctype/payroll_entry/payroll_entry.py index 67893448ba4..7a70679db47 100644 --- a/erpnext/payroll/doctype/payroll_entry/payroll_entry.py +++ b/erpnext/payroll/doctype/payroll_entry/payroll_entry.py @@ -665,6 +665,8 @@ def get_employee_list(filters): emp_list = remove_payrolled_employees(emp_list, filters.start_date, filters.end_date) return emp_list + return [] + @frappe.whitelist() @frappe.validate_and_sanitize_search_inputs def employee_query(doctype, txt, searchfield, start, page_len, filters): @@ -673,7 +675,7 @@ def employee_query(doctype, txt, searchfield, start, page_len, filters): include_employees = [] emp_cond = '' if filters.start_date and filters.end_date: - employee_list = get_employee_list(filters) or [] + employee_list = get_employee_list(filters) emp = filters.get('employees') include_employees = [employee.employee for employee in employee_list if employee.employee not in emp] filters.pop('start_date') From f310501d7dd8142bd50cd072e794eeaeab272820 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Thu, 3 Jun 2021 17:57:01 +0530 Subject: [PATCH 128/135] fix: filter type for item query --- erpnext/controllers/queries.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py index 638503edfa9..81ac234e700 100644 --- a/erpnext/controllers/queries.py +++ b/erpnext/controllers/queries.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals import frappe import erpnext +import json from frappe.desk.reportview import get_match_cond, get_filters_cond from frappe.utils import nowdate, getdate from collections import defaultdict @@ -198,6 +199,9 @@ def tax_account_query(doctype, txt, searchfield, start, page_len, filters): def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=False): conditions = [] + if isinstance(filters, str): + filters = json.loads(filters) + #Get searchfields from meta and use in Item Link field query meta = frappe.get_meta("Item", cached=True) searchfields = meta.get_search_fields() From b103b24ae164aaa5702b50f091c699e09a77898a Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Thu, 27 May 2021 17:05:36 +0530 Subject: [PATCH 129/135] fix: timeout error in the repost item valuation --- erpnext/hooks.py | 4 +++- .../repost_item_valuation/repost_item_valuation.py | 13 ++++--------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 0cdbbde61ba..22ce4df97cf 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -333,7 +333,9 @@ scheduler_events = { "erpnext.projects.doctype.project.project.collect_project_status", "erpnext.hr.doctype.shift_type.shift_type.process_auto_attendance_for_all_shifts", "erpnext.support.doctype.issue.issue.set_service_level_agreement_variance", - "erpnext.erpnext_integrations.connectors.shopify_connection.sync_old_orders", + "erpnext.erpnext_integrations.connectors.shopify_connection.sync_old_orders" + ], + "hourly_long": [ "erpnext.stock.doctype.repost_item_valuation.repost_item_valuation.repost_entries" ], "daily": [ diff --git a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py index 5b626ea3458..55f2ebb2241 100644 --- a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py +++ b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py @@ -37,6 +37,9 @@ class RepostItemValuation(Document): self.db_set('status', status) def on_submit(self): + if not frappe.flags.in_test: + return + frappe.enqueue(repost, timeout=1800, queue='long', job_name='repost_sle', now=frappe.flags.in_test, doc=self) @@ -115,12 +118,6 @@ def notify_error_to_stock_managers(doc, traceback): frappe.sendmail(recipients=recipients, subject=subject, message=message) def repost_entries(): - job_log = frappe.get_all('Scheduled Job Log', fields = ['status', 'creation'], - filters = {'scheduled_job_type': 'repost_item_valuation.repost_entries'}, order_by='creation desc', limit=1) - - if job_log and job_log[0]['status'] == 'Start' and time_diff_in_hours(now(), job_log[0]['creation']) < 2: - return - riv_entries = get_repost_item_valuation_entries() for row in riv_entries: @@ -135,9 +132,7 @@ def repost_entries(): check_if_stock_and_account_balance_synced(today(), d.name) def get_repost_item_valuation_entries(): - date = add_to_date(now(), hours=-3) - return frappe.db.sql(""" SELECT name from `tabRepost Item Valuation` WHERE status != 'Completed' and creation <= %s and docstatus = 1 ORDER BY timestamp(posting_date, posting_time) asc, creation asc - """, date, as_dict=1) + """, now(), as_dict=1) From 9cfd3adad93a5138895b5a47ec5a85802bcfd691 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Fri, 4 Jun 2021 10:53:44 +0530 Subject: [PATCH 130/135] fix: custom conversion factor field not mapped from job card to stock entry --- erpnext/manufacturing/doctype/job_card/job_card.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/manufacturing/doctype/job_card/job_card.py b/erpnext/manufacturing/doctype/job_card/job_card.py index fb26062566a..d764db33f86 100644 --- a/erpnext/manufacturing/doctype/job_card/job_card.py +++ b/erpnext/manufacturing/doctype/job_card/job_card.py @@ -433,7 +433,8 @@ def make_material_request(source_name, target_doc=None): def make_stock_entry(source_name, target_doc=None): def update_item(obj, target, source_parent): target.t_warehouse = source_parent.wip_warehouse - target.conversion_factor = 1 + if not target.conversion_factor: + target.conversion_factor = 1 def set_missing_values(source, target): target.purpose = "Material Transfer for Manufacture" From 17408c63885b5cfc1abc95131b69b4b6c1364c68 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Wed, 9 Jun 2021 00:06:35 +0530 Subject: [PATCH 131/135] fix: on click of duplicate button system copy the difference account from first row --- erpnext/stock/doctype/stock_entry/stock_entry.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js index 9c4f0ddcbc9..7952adb0328 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.js +++ b/erpnext/stock/doctype/stock_entry/stock_entry.js @@ -978,7 +978,10 @@ erpnext.stock.StockEntry = class StockEntry extends erpnext.stock.StockControlle items_add(doc, cdt, cdn) { var row = frappe.get_doc(cdt, cdn); - this.frm.script_manager.copy_from_first_row("items", row, ["expense_account", "cost_center"]); + + if (!(row.expense_account && row.cost_center)) { + this.frm.script_manager.copy_from_first_row("items", row, ["expense_account", "cost_center"]); + } if(!row.s_warehouse) row.s_warehouse = this.frm.doc.from_warehouse; if(!row.t_warehouse) row.t_warehouse = this.frm.doc.to_warehouse; From a424c0c023e11647f09a55fbda0321fc5f3c31ef Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Fri, 11 Jun 2021 16:49:39 +0530 Subject: [PATCH 132/135] test(perf): eliminate repeat creation of HSN codes (bp #25947) --- erpnext/regional/india/setup.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py index 229e0c031e3..3e0b9b733b6 100644 --- a/erpnext/regional/india/setup.py +++ b/erpnext/regional/india/setup.py @@ -27,6 +27,9 @@ def setup_company_independent_fixtures(patch=False): add_print_formats() def add_hsn_sac_codes(): + if frappe.flags.in_test and frappe.flags.created_hsn_codes: + return + # HSN codes with open(os.path.join(os.path.dirname(__file__), 'hsn_code_data.json'), 'r') as f: hsn_codes = json.loads(f.read()) @@ -38,6 +41,9 @@ def add_hsn_sac_codes(): sac_codes = json.loads(f.read()) create_hsn_codes(sac_codes, code_field="sac_code") + if frappe.flags.in_test: + frappe.flags.created_hsn_codes = True + def create_hsn_codes(data, code_field): for d in data: hsn_code = frappe.new_doc('GST HSN Code') From 9891780f5aaa76a2dd6cf49c189013cead668e70 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Fri, 11 Jun 2021 18:40:22 +0530 Subject: [PATCH 133/135] perf(minor): remove unnecessary comprehensions (port #25645) --- erpnext/accounts/doctype/c_form/c_form.py | 2 +- .../doctype/coupon_code/coupon_code.py | 2 +- .../invoice_discounting/invoice_discounting.py | 2 +- .../doctype/journal_entry/journal_entry.py | 4 ++-- .../monthly_distribution.py | 2 +- .../doctype/payment_entry/payment_entry.py | 10 +++++----- .../doctype/payment_request/payment_request.py | 2 +- erpnext/accounts/doctype/pricing_rule/utils.py | 18 +++++++++--------- .../purchase_invoice/test_purchase_invoice.py | 2 +- .../test_tax_withholding_category.py | 2 +- erpnext/accounts/general_ledger.py | 2 +- .../report/cash_flow/custom_cash_flow.py | 8 ++++---- .../customer_ledger_summary.py | 2 +- .../accounts/report/financial_statements.py | 2 +- .../item_wise_purchase_register.py | 2 +- .../item_wise_sales_register.py | 2 +- .../report/pos_register/pos_register.py | 6 +++--- .../purchase_register/purchase_register.py | 14 +++++++------- .../sales_payment_summary.py | 4 ++-- .../report/sales_register/sales_register.py | 16 ++++++++-------- .../tds_computation_summary.py | 4 ++-- erpnext/accounts/report/utils.py | 2 +- erpnext/accounts/utils.py | 2 +- erpnext/assets/doctype/asset/test_asset.py | 2 +- .../asset_value_adjustment.py | 2 +- .../doctype/purchase_order/purchase_order.py | 6 +++--- .../purchase_order/test_purchase_order.py | 2 +- .../request_for_quotation.py | 2 +- erpnext/controllers/accounts_controller.py | 8 ++++---- erpnext/controllers/buying_controller.py | 6 +++--- erpnext/controllers/queries.py | 2 +- erpnext/controllers/selling_controller.py | 2 +- erpnext/controllers/status_updater.py | 4 ++-- erpnext/controllers/stock_controller.py | 6 +++--- erpnext/controllers/taxes_and_totals.py | 12 ++++++------ erpnext/controllers/tests/test_mapper.py | 4 ++-- .../controllers/website_list_for_contact.py | 2 +- .../manufacturing/doctype/job_card/job_card.py | 2 +- erpnext/projects/doctype/task/task.py | 2 +- .../projects/doctype/timesheet/timesheet.py | 4 ++-- .../report/project_summary/project_summary.py | 2 +- erpnext/selling/doctype/customer/customer.py | 2 +- erpnext/selling/doctype/quotation/quotation.py | 2 +- .../selling/doctype/sales_order/sales_order.py | 2 +- erpnext/setup/doctype/company/company.py | 4 ++-- erpnext/setup/doctype/item_group/item_group.py | 4 ++-- erpnext/stock/doctype/batch/batch.py | 2 +- .../doctype/delivery_note/delivery_note.py | 2 +- .../doctype/delivery_trip/delivery_trip.py | 6 +++--- .../landed_cost_voucher/landed_cost_voucher.py | 8 ++++---- .../test_landed_cost_voucher.py | 2 +- .../stock/doctype/packing_slip/packing_slip.py | 4 ++-- .../purchase_receipt/test_purchase_receipt.py | 2 +- erpnext/stock/doctype/serial_no/serial_no.py | 2 +- .../stock/doctype/stock_entry/stock_entry.py | 2 +- .../item_price_stock/item_price_stock.py | 2 +- .../itemwise_recommended_reorder_level.py | 2 +- .../product_bundle_balance.py | 2 +- .../report/stock_balance/stock_balance.py | 6 +++--- .../stock/report/stock_ledger/stock_ledger.py | 4 ++-- erpnext/stock/stock_ledger.py | 2 +- .../doctype/warranty_claim/warranty_claim.py | 2 +- erpnext/utilities/product.py | 2 +- erpnext/utilities/transaction_base.py | 4 ++-- 64 files changed, 126 insertions(+), 126 deletions(-) diff --git a/erpnext/accounts/doctype/c_form/c_form.py b/erpnext/accounts/doctype/c_form/c_form.py index fd86ed4c90e..cfe28f3ff9f 100644 --- a/erpnext/accounts/doctype/c_form/c_form.py +++ b/erpnext/accounts/doctype/c_form/c_form.py @@ -54,7 +54,7 @@ class CForm(Document): frappe.throw(_("Please enter atleast 1 invoice in the table")) def set_total_invoiced_amount(self): - total = sum([flt(d.grand_total) for d in self.get('invoices')]) + total = sum(flt(d.grand_total) for d in self.get('invoices')) frappe.db.set(self, 'total_invoiced_amount', total) @frappe.whitelist() diff --git a/erpnext/accounts/doctype/coupon_code/coupon_code.py b/erpnext/accounts/doctype/coupon_code/coupon_code.py index 7829c9320d7..55c119315e0 100644 --- a/erpnext/accounts/doctype/coupon_code/coupon_code.py +++ b/erpnext/accounts/doctype/coupon_code/coupon_code.py @@ -14,7 +14,7 @@ class CouponCode(Document): if not self.coupon_code: if self.coupon_type == "Promotional": - self.coupon_code =''.join([i for i in self.coupon_name if not i.isdigit()])[0:8].upper() + self.coupon_code =''.join(i for i in self.coupon_name if not i.isdigit())[0:8].upper() elif self.coupon_type == "Gift Card": self.coupon_code = frappe.generate_hash()[:10].upper() diff --git a/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py b/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py index 7b62b617f97..d1e5afc48ff 100644 --- a/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py +++ b/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py @@ -42,7 +42,7 @@ class InvoiceDiscounting(AccountsController): record.idx, frappe.bold(actual_outstanding), frappe.bold(record.sales_invoice))) def calculate_total_amount(self): - self.total_amount = sum([flt(d.outstanding_amount) for d in self.invoices]) + self.total_amount = sum(flt(d.outstanding_amount) for d in self.invoices) def on_submit(self): self.update_sales_invoice() diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index ed1bd282235..937597bc550 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -196,8 +196,8 @@ class JournalEntry(AccountsController): frappe.throw(_("Row {0}: Party Type and Party is required for Receivable / Payable account {1}").format(d.idx, d.account)) def check_credit_limit(self): - customers = list(set([d.party for d in self.get("accounts") - if d.party_type=="Customer" and d.party and flt(d.debit) > 0])) + customers = list(set(d.party for d in self.get("accounts") + if d.party_type=="Customer" and d.party and flt(d.debit) > 0)) if customers: from erpnext.selling.doctype.customer.customer import check_credit_limit for customer in customers: diff --git a/erpnext/accounts/doctype/monthly_distribution/monthly_distribution.py b/erpnext/accounts/doctype/monthly_distribution/monthly_distribution.py index 88667d72076..bff64227325 100644 --- a/erpnext/accounts/doctype/monthly_distribution/monthly_distribution.py +++ b/erpnext/accounts/doctype/monthly_distribution/monthly_distribution.py @@ -21,7 +21,7 @@ class MonthlyDistribution(Document): idx += 1 def validate(self): - total = sum([flt(d.percentage_allocation) for d in self.get("percentages")]) + total = sum(flt(d.percentage_allocation) for d in self.get("percentages")) if flt(total, 2) != 100.0: frappe.throw(_("Percentage Allocation should be equal to 100%") + \ diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index 62ab76c3238..544d5305513 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -303,7 +303,7 @@ class PaymentEntry(AccountsController): for k, v in no_oustanding_refs.items(): frappe.msgprint( _("{} - {} now have {} as they had no outstanding amount left before submitting the Payment Entry.") - .format(k, frappe.bold(", ".join([d.reference_name for d in v])), frappe.bold("negative outstanding amount")) + .format(k, frappe.bold(", ".join(d.reference_name for d in v)), frappe.bold("negative outstanding amount")) + "

    " + _("If this is undesirable please cancel the corresponding Payment Entry."), title=_("Warning"), indicator="orange") @@ -419,7 +419,7 @@ class PaymentEntry(AccountsController): def set_unallocated_amount(self): self.unallocated_amount = 0 if self.party: - total_deductions = sum([flt(d.amount) for d in self.get("deductions")]) + total_deductions = sum(flt(d.amount) for d in self.get("deductions")) if self.payment_type == "Receive" \ and self.base_total_allocated_amount < self.base_received_amount + total_deductions \ and self.total_allocated_amount < self.paid_amount + (total_deductions / self.source_exchange_rate): @@ -444,7 +444,7 @@ class PaymentEntry(AccountsController): else: self.difference_amount = self.base_paid_amount - flt(self.base_received_amount) - total_deductions = sum([flt(d.amount) for d in self.get("deductions")]) + total_deductions = sum(flt(d.amount) for d in self.get("deductions")) self.difference_amount = flt(self.difference_amount - total_deductions, self.precision("difference_amount")) @@ -460,8 +460,8 @@ class PaymentEntry(AccountsController): if ((self.payment_type=="Pay" and self.party_type=="Customer") or (self.payment_type=="Receive" and self.party_type=="Supplier")): - total_negative_outstanding = sum([abs(flt(d.outstanding_amount)) - for d in self.get("references") if flt(d.outstanding_amount) < 0]) + total_negative_outstanding = sum(abs(flt(d.outstanding_amount)) + for d in self.get("references") if flt(d.outstanding_amount) < 0) paid_amount = self.paid_amount if self.payment_type=="Receive" else self.received_amount additional_charges = sum([flt(d.amount) for d in self.deductions]) diff --git a/erpnext/accounts/doctype/payment_request/payment_request.py b/erpnext/accounts/doctype/payment_request/payment_request.py index 53ac996290b..520e87a6ce1 100644 --- a/erpnext/accounts/doctype/payment_request/payment_request.py +++ b/erpnext/accounts/doctype/payment_request/payment_request.py @@ -112,7 +112,7 @@ class PaymentRequest(Document): if not data_of_completed_requests: return self.grand_total - request_amounts = sum([json.loads(d).get('request_amount') for d in data_of_completed_requests]) + request_amounts = sum(json.loads(d).get('request_amount') for d in data_of_completed_requests) return request_amounts def on_cancel(self): diff --git a/erpnext/accounts/doctype/pricing_rule/utils.py b/erpnext/accounts/doctype/pricing_rule/utils.py index d23b952bdc2..b54d0e73a8c 100644 --- a/erpnext/accounts/doctype/pricing_rule/utils.py +++ b/erpnext/accounts/doctype/pricing_rule/utils.py @@ -20,9 +20,9 @@ from frappe.utils import cint, flt, get_link_to_form, getdate, today, fmt_money class MultiplePricingRuleConflict(frappe.ValidationError): pass apply_on_table = { - 'Item Code': 'items', - 'Item Group': 'item_groups', - 'Brand': 'brands' + 'Item Code': 'items', + 'Item Group': 'item_groups', + 'Brand': 'brands' } def get_pricing_rules(args, doc=None): @@ -183,7 +183,7 @@ def _get_tree_conditions(args, parenttype, table, allow_blank=True): condition = "ifnull({table}.{field}, '') in ({parent_groups})".format( table=table, field=field, - parent_groups=", ".join([frappe.db.escape(d) for d in parent_groups]) + parent_groups=", ".join(frappe.db.escape(d) for d in parent_groups) ) frappe.flags.tree_conditions[key] = condition @@ -264,7 +264,7 @@ def filter_pricing_rules(args, pricing_rules, doc=None): # find pricing rule with highest priority if pricing_rules: - max_priority = max([cint(p.priority) for p in 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)) @@ -272,14 +272,14 @@ def filter_pricing_rules(args, pricing_rules, doc=None): pricing_rules = list(pricing_rules) if len(pricing_rules) > 1: - rate_or_discount = list(set([d.rate_or_discount for d in pricing_rules])) + 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 = list(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) + .format("\n".join(d.name for d in pricing_rules)), MultiplePricingRuleConflict) elif pricing_rules: return pricing_rules[0] @@ -541,7 +541,7 @@ def get_product_discount_rule(pricing_rule, item_details, args=None, doc=None): def apply_pricing_rule_for_free_items(doc, pricing_rule_args, set_missing_values=False): if pricing_rule_args: - items = tuple([(d.item_code, d.pricing_rules) for d in doc.items if d.is_free_item]) + items = tuple((d.item_code, d.pricing_rules) for d in doc.items if d.is_free_item) for args in pricing_rule_args: if not items or (args.get('item_code'), args.get('pricing_rules')) not in items: @@ -589,4 +589,4 @@ def update_coupon_code_count(coupon_name,transaction_type): elif transaction_type=='cancelled': if coupon.used>0: coupon.used=coupon.used-1 - coupon.save(ignore_permissions=True) \ No newline at end of file + coupon.save(ignore_permissions=True) diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index 53db689c84a..6dc0f56148b 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -631,7 +631,7 @@ class TestPurchaseInvoice(unittest.TestCase): self.assertEqual(len(pi.get("supplied_items")), 2) - rm_supp_cost = sum([d.amount for d in pi.get("supplied_items")]) + rm_supp_cost = sum(d.amount for d in pi.get("supplied_items")) self.assertEqual(flt(pi.get("items")[0].rm_supp_cost, 2), flt(rm_supp_cost, 2)) def test_rejected_serial_no(self): diff --git a/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py b/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py index 0cea7612dd3..dd26be7c992 100644 --- a/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py +++ b/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py @@ -112,7 +112,7 @@ class TestTaxWithholdingCategory(unittest.TestCase): si = create_sales_invoice(customer = "Test TCS Customer", rate=5000) si.submit() - tcs_charged = sum([d.base_tax_amount for d in si.taxes if d.account_head == 'TCS - _TC']) + tcs_charged = sum(d.base_tax_amount for d in si.taxes if d.account_head == 'TCS - _TC') self.assertEqual(tcs_charged, 500) invoices.append(si) diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py index f1717c50d8d..968ab49b312 100644 --- a/erpnext/accounts/general_ledger.py +++ b/erpnext/accounts/general_ledger.py @@ -143,7 +143,7 @@ def make_entry(args, adv_adj, update_outstanding, from_repost=False): validate_expense_against_budget(args) def validate_cwip_accounts(gl_map): - cwip_enabled = any([cint(ac.enable_cwip_accounting) for ac in frappe.db.get_all("Asset Category","enable_cwip_accounting")]) + cwip_enabled = any(cint(ac.enable_cwip_accounting) for ac in frappe.db.get_all("Asset Category","enable_cwip_accounting")) if cwip_enabled and gl_map[0].voucher_type == "Journal Entry": cwip_accounts = [d[0] for d in frappe.db.sql("""select name from tabAccount diff --git a/erpnext/accounts/report/cash_flow/custom_cash_flow.py b/erpnext/accounts/report/cash_flow/custom_cash_flow.py index ff87276a876..c11c15390b3 100644 --- a/erpnext/accounts/report/cash_flow/custom_cash_flow.py +++ b/erpnext/accounts/report/cash_flow/custom_cash_flow.py @@ -32,7 +32,7 @@ def get_accounts_in_mappers(mapping_names): join `tabCash Flow Mapping` cfm on cfma.parent=cfm.name where cfma.parent in (%s) order by cfm.is_working_capital - ''', (', '.join(['"%s"' % d for d in mapping_names]))) + ''', (', '.join('"%s"' % d for d in mapping_names))) def setup_mappers(mappers): @@ -83,8 +83,8 @@ def setup_mappers(mappers): account_types_labels = sorted( set( - [(d['label'], d['is_working_capital'], d['is_income_tax_liability'], d['is_income_tax_expense']) - for d in account_types] + (d['label'], d['is_working_capital'], d['is_income_tax_liability'], d['is_income_tax_expense']) + for d in account_types ), key=lambda x: x[1] ) @@ -375,7 +375,7 @@ def _get_account_type_based_data(filters, account_names, period_list, accumulate total = 0 for period in period_list: start_date = get_start_date(period, accumulated_values, company) - accounts = ', '.join(['"%s"' % d for d in account_names]) + accounts = ', '.join('"%s"' % d for d in account_names) if opening_balances: date_info = dict(date=start_date) diff --git a/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py b/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py index 10b32fea562..c79d7401e6a 100644 --- a/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py +++ b/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py @@ -145,7 +145,7 @@ class PartyLedgerSummaryReport(object): out = [] for party, row in iteritems(self.party_data): if row.opening_balance or row.invoiced_amount or row.paid_amount or row.return_amount or row.closing_amount: - total_party_adjustment = sum([amount for amount in itervalues(self.party_adjustment_details.get(party, {}))]) + total_party_adjustment = sum(amount for amount in itervalues(self.party_adjustment_details.get(party, {}))) row.paid_amount -= total_party_adjustment adjustments = self.party_adjustment_details.get(party, {}) diff --git a/erpnext/accounts/report/financial_statements.py b/erpnext/accounts/report/financial_statements.py index d20ddbde5c6..39ff8045181 100644 --- a/erpnext/accounts/report/financial_statements.py +++ b/erpnext/accounts/report/financial_statements.py @@ -369,7 +369,7 @@ def set_gl_entries_by_account( if accounts: additional_conditions += " and account in ({})"\ - .format(", ".join([frappe.db.escape(d) for d in accounts])) + .format(", ".join(frappe.db.escape(d) for d in accounts)) gl_filters = { "company": company, diff --git a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py index cb4d9b43dbd..685419a17e4 100644 --- a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py +++ b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py @@ -334,7 +334,7 @@ def get_aii_accounts(): def get_purchase_receipts_against_purchase_order(item_list): po_pr_map = frappe._dict() - po_item_rows = list(set([d.po_detail for d in item_list])) + po_item_rows = list(set(d.po_detail for d in item_list)) if po_item_rows: purchase_receipts = frappe.db.sql(""" diff --git a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py index 928b373effe..2e794da8425 100644 --- a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py +++ b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py @@ -23,7 +23,7 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum if item_list: itemised_tax, tax_columns = get_tax_accounts(item_list, columns, company_currency) - mode_of_payments = get_mode_of_payments(set([d.parent for d in item_list])) + mode_of_payments = get_mode_of_payments(set(d.parent for d in item_list)) so_dn_map = get_delivery_notes_against_sales_order(item_list) data = [] diff --git a/erpnext/accounts/report/pos_register/pos_register.py b/erpnext/accounts/report/pos_register/pos_register.py index cfbd7fd0c8b..6a42bb4fb65 100644 --- a/erpnext/accounts/report/pos_register/pos_register.py +++ b/erpnext/accounts/report/pos_register/pos_register.py @@ -77,14 +77,14 @@ def get_pos_entries(filters, group_by_field): ), filters, as_dict=1) def concat_mode_of_payments(pos_entries): - mode_of_payments = get_mode_of_payments(set([d.pos_invoice for d in pos_entries])) + mode_of_payments = get_mode_of_payments(set(d.pos_invoice for d in pos_entries)) for entry in pos_entries: if mode_of_payments.get(entry.pos_invoice): entry.mode_of_payment = ", ".join(mode_of_payments.get(entry.pos_invoice, [])) def add_subtotal_row(data, group_invoices, group_by_field, group_by_value): - grand_total = sum([d.grand_total for d in group_invoices]) - paid_amount = sum([d.paid_amount for d in group_invoices]) + grand_total = sum(d.grand_total for d in group_invoices) + paid_amount = sum(d.paid_amount for d in group_invoices) data.append({ group_by_field: group_by_value, "grand_total": grand_total, diff --git a/erpnext/accounts/report/purchase_register/purchase_register.py b/erpnext/accounts/report/purchase_register/purchase_register.py index 8ac749d6290..10edd41aa88 100644 --- a/erpnext/accounts/report/purchase_register/purchase_register.py +++ b/erpnext/accounts/report/purchase_register/purchase_register.py @@ -26,7 +26,7 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum invoice_expense_map, invoice_tax_map = get_invoice_tax_map(invoice_list, invoice_expense_map, expense_accounts) invoice_po_pr_map = get_invoice_po_pr_map(invoice_list) - suppliers = list(set([d.supplier for d in invoice_list])) + suppliers = list(set(d.supplier for d in invoice_list)) supplier_details = get_supplier_details(suppliers) company_currency = frappe.get_cached_value('Company', filters.company, "default_currency") @@ -120,13 +120,13 @@ def get_columns(invoice_list, additional_table_columns): and docstatus = 1 and (account_head is not null and account_head != '') and category in ('Total', 'Valuation and Total') and parent in (%s) order by account_head""" % - ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list])) + ', '.join(['%s']*len(invoice_list)), tuple(inv.name for inv in invoice_list)) unrealized_profit_loss_accounts = frappe.db.sql_list("""SELECT distinct unrealized_profit_loss_account from `tabPurchase Invoice` where docstatus = 1 and name in (%s) and ifnull(unrealized_profit_loss_account, '') != '' order by unrealized_profit_loss_account""" % - ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list])) + ', '.join(['%s']*len(invoice_list)), tuple(inv.name for inv in invoice_list)) expense_columns = [(account + ":Currency/currency:120") for account in expense_accounts] unrealized_profit_loss_account_columns = [(account + ":Currency/currency:120") for account in unrealized_profit_loss_accounts] @@ -208,7 +208,7 @@ def get_invoice_expense_map(invoice_list): from `tabPurchase Invoice Item` where parent in (%s) group by parent, expense_account - """ % ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1) + """ % ', '.join(['%s']*len(invoice_list)), tuple(inv.name for inv in invoice_list), as_dict=1) invoice_expense_map = {} for d in expense_details: @@ -221,7 +221,7 @@ def get_internal_invoice_map(invoice_list): unrealized_amount_details = frappe.db.sql("""SELECT name, unrealized_profit_loss_account, base_net_total as amount from `tabPurchase Invoice` where name in (%s) and is_internal_supplier = 1 and company = represents_company""" % - ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1) + ', '.join(['%s']*len(invoice_list)), tuple(inv.name for inv in invoice_list), as_dict=1) internal_invoice_map = {} for d in unrealized_amount_details: @@ -238,7 +238,7 @@ def get_invoice_tax_map(invoice_list, invoice_expense_map, expense_accounts): where parent in (%s) and category in ('Total', 'Valuation and Total') and base_tax_amount_after_discount_amount != 0 group by parent, account_head, add_deduct_tax - """ % ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1) + """ % ', '.join(['%s']*len(invoice_list)), tuple(inv.name for inv in invoice_list), as_dict=1) invoice_tax_map = {} for d in tax_details: @@ -258,7 +258,7 @@ def get_invoice_po_pr_map(invoice_list): select parent, purchase_order, purchase_receipt, po_detail, project from `tabPurchase Invoice Item` where parent in (%s) - """ % ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1) + """ % ', '.join(['%s']*len(invoice_list)), tuple(inv.name for inv in invoice_list), as_dict=1) invoice_po_pr_map = {} for d in pi_items: diff --git a/erpnext/accounts/report/sales_payment_summary/sales_payment_summary.py b/erpnext/accounts/report/sales_payment_summary/sales_payment_summary.py index c234da0fe39..ff774681a29 100644 --- a/erpnext/accounts/report/sales_payment_summary/sales_payment_summary.py +++ b/erpnext/accounts/report/sales_payment_summary/sales_payment_summary.py @@ -158,7 +158,7 @@ def get_sales_invoice_data(filters): def get_mode_of_payments(filters): mode_of_payments = {} invoice_list = get_invoices(filters) - invoice_list_names = ",".join(['"' + invoice['name'] + '"' for invoice in invoice_list]) + invoice_list_names = ",".join('"' + invoice['name'] + '"' for invoice in invoice_list) if invoice_list: inv_mop = frappe.db.sql("""select a.owner,a.posting_date, ifnull(b.mode_of_payment, '') as mode_of_payment from `tabSales Invoice` a, `tabSales Invoice Payment` b @@ -197,7 +197,7 @@ def get_invoices(filters): def get_mode_of_payment_details(filters): mode_of_payment_details = {} invoice_list = get_invoices(filters) - invoice_list_names = ",".join(['"' + invoice['name'] + '"' for invoice in invoice_list]) + invoice_list_names = ",".join('"' + invoice['name'] + '"' for invoice in invoice_list) if invoice_list: inv_mop_detail = frappe.db.sql("""select a.owner, a.posting_date, ifnull(b.mode_of_payment, '') as mode_of_payment, sum(b.base_amount) as paid_amount diff --git a/erpnext/accounts/report/sales_register/sales_register.py b/erpnext/accounts/report/sales_register/sales_register.py index cb2c98b64ae..909959323f7 100644 --- a/erpnext/accounts/report/sales_register/sales_register.py +++ b/erpnext/accounts/report/sales_register/sales_register.py @@ -248,19 +248,19 @@ def get_columns(invoice_list, additional_table_columns): income_accounts = frappe.db.sql_list("""select distinct income_account from `tabSales Invoice Item` where docstatus = 1 and parent in (%s) order by income_account""" % - ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list])) + ', '.join(['%s']*len(invoice_list)), tuple(inv.name for inv in invoice_list)) tax_accounts = frappe.db.sql_list("""select distinct account_head from `tabSales Taxes and Charges` where parenttype = 'Sales Invoice' and docstatus = 1 and base_tax_amount_after_discount_amount != 0 and parent in (%s) order by account_head""" % - ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list])) + ', '.join(['%s']*len(invoice_list)), tuple(inv.name for inv in invoice_list)) unrealized_profit_loss_accounts = frappe.db.sql_list("""SELECT distinct unrealized_profit_loss_account from `tabSales Invoice` where docstatus = 1 and name in (%s) and ifnull(unrealized_profit_loss_account, '') != '' order by unrealized_profit_loss_account""" % - ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list])) + ', '.join(['%s']*len(invoice_list)), tuple(inv.name for inv in invoice_list)) for account in income_accounts: income_columns.append({ @@ -406,7 +406,7 @@ def get_invoices(filters, additional_query_columns): def get_invoice_income_map(invoice_list): income_details = frappe.db.sql("""select parent, income_account, sum(base_net_amount) as amount from `tabSales Invoice Item` where parent in (%s) group by parent, income_account""" % - ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1) + ', '.join(['%s']*len(invoice_list)), tuple(inv.name for inv in invoice_list), as_dict=1) invoice_income_map = {} for d in income_details: @@ -419,7 +419,7 @@ def get_internal_invoice_map(invoice_list): unrealized_amount_details = frappe.db.sql("""SELECT name, unrealized_profit_loss_account, base_net_total as amount from `tabSales Invoice` where name in (%s) and is_internal_customer = 1 and company = represents_company""" % - ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1) + ', '.join(['%s']*len(invoice_list)), tuple(inv.name for inv in invoice_list), as_dict=1) internal_invoice_map = {} for d in unrealized_amount_details: @@ -432,7 +432,7 @@ def get_invoice_tax_map(invoice_list, invoice_income_map, income_accounts): tax_details = frappe.db.sql("""select parent, account_head, sum(base_tax_amount_after_discount_amount) as tax_amount from `tabSales Taxes and Charges` where parent in (%s) group by parent, account_head""" % - ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1) + ', '.join(['%s']*len(invoice_list)), tuple(inv.name for inv in invoice_list), as_dict=1) invoice_tax_map = {} for d in tax_details: @@ -451,7 +451,7 @@ def get_invoice_so_dn_map(invoice_list): si_items = frappe.db.sql("""select parent, sales_order, delivery_note, so_detail from `tabSales Invoice Item` where parent in (%s) and (ifnull(sales_order, '') != '' or ifnull(delivery_note, '') != '')""" % - ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1) + ', '.join(['%s']*len(invoice_list)), tuple(inv.name for inv in invoice_list), as_dict=1) invoice_so_dn_map = {} for d in si_items: @@ -475,7 +475,7 @@ def get_invoice_cc_wh_map(invoice_list): si_items = frappe.db.sql("""select parent, cost_center, warehouse from `tabSales Invoice Item` where parent in (%s) and (ifnull(cost_center, '') != '' or ifnull(warehouse, '') != '')""" % - ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1) + ', '.join(['%s']*len(invoice_list)), tuple(inv.name for inv in invoice_list), as_dict=1) invoice_cc_wh_map = {} for d in si_items: diff --git a/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py b/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py index a8280c1b18e..e15715dccd8 100644 --- a/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py +++ b/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py @@ -78,7 +78,7 @@ def get_invoice_and_tds_amount(supplier, account, company, from_date, to_date, f and company=%s and posting_date between %s and %s """, (supplier, company, from_date, to_date), as_dict=1) - supplier_credit_amount = flt(sum([d.credit for d in entries])) + supplier_credit_amount = flt(sum(d.credit for d in entries)) vouchers = [d.voucher_no for d in entries] vouchers += get_advance_vouchers([supplier], company=company, @@ -91,7 +91,7 @@ def get_invoice_and_tds_amount(supplier, account, company, from_date, to_date, f from `tabGL Entry` where account=%s and posting_date between %s and %s and company=%s and credit > 0 and voucher_no in ({0}) - """.format(', '.join(["'%s'" % d for d in vouchers])), + """.format(', '.join("'%s'" % d for d in vouchers)), (account, from_date, to_date, company))[0][0]) date_range_filter = [fiscal_year, from_date, to_date] diff --git a/erpnext/accounts/report/utils.py b/erpnext/accounts/report/utils.py index b020d0a5062..ba461edaf86 100644 --- a/erpnext/accounts/report/utils.py +++ b/erpnext/accounts/report/utils.py @@ -139,6 +139,6 @@ def get_invoiced_item_gross_margin(sales_invoice=None, item_code=None, company=N gross_profit_data = GrossProfitGenerator(filters) result = gross_profit_data.grouped_data if not with_item_data: - result = sum([d.gross_profit for d in result]) + result = sum(d.gross_profit for d in result) return result diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index 5a64e27ccb7..66a9b601257 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -635,7 +635,7 @@ def get_held_invoices(party_type, party): 'select name from `tabPurchase Invoice` where release_date IS NOT NULL and release_date > CURDATE()', as_dict=1 ) - held_invoices = set([d['name'] for d in held_invoices]) + held_invoices = set(d['name'] for d in held_invoices) return held_invoices diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index 3cd4b802c11..8845f24d104 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -470,7 +470,7 @@ class TestAsset(unittest.TestCase): }) asset.insert() accumulated_depreciation_after_full_schedule = \ - max([d.accumulated_depreciation_amount for d in asset.get("schedules")]) + max(d.accumulated_depreciation_amount for d in asset.get("schedules")) asset_value_after_full_schedule = (flt(asset.gross_purchase_amount) - flt(accumulated_depreciation_after_full_schedule)) diff --git a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py index 14308277c14..2f6b5ee2dc9 100644 --- a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py +++ b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py @@ -92,7 +92,7 @@ class AssetValueAdjustment(Document): d.value_after_depreciation = asset_value if d.depreciation_method in ("Straight Line", "Manual"): - end_date = max([s.schedule_date for s in asset.schedules if cint(s.finance_book_id) == d.idx]) + end_date = max(s.schedule_date for s in asset.schedules if cint(s.finance_book_id) == d.idx) total_days = date_diff(end_date, self.date) rate_per_day = flt(d.value_after_depreciation) / flt(total_days) from_date = self.date diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index ef9372eeb65..c023accbfc0 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -104,7 +104,7 @@ class PurchaseOrder(BuyingController): def validate_minimum_order_qty(self): if not self.get("items"): return - items = list(set([d.item_code for d in self.get("items")])) + items = list(set(d.item_code for d in self.get("items"))) itemwise_min_order_qty = frappe._dict(frappe.db.sql("""select name, min_order_qty from tabItem where name in ({0})""".format(", ".join(["%s"] * len(items))), items)) @@ -291,10 +291,10 @@ class PurchaseOrder(BuyingController): so.notify_update() def has_drop_ship_item(self): - return any([d.delivered_by_supplier for d in self.items]) + return any(d.delivered_by_supplier for d in self.items) def is_against_so(self): - return any([d.sales_order for d in self.items if d.sales_order]) + return any(d.sales_order for d in self.items if d.sales_order) def set_received_qty_for_drop_ship_items(self): for item in self.items: diff --git a/erpnext/buying/doctype/purchase_order/test_purchase_order.py b/erpnext/buying/doctype/purchase_order/test_purchase_order.py index aaa98f2f1f4..565fc920b8e 100644 --- a/erpnext/buying/doctype/purchase_order/test_purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/test_purchase_order.py @@ -359,7 +359,7 @@ class TestPurchaseOrder(unittest.TestCase): update_child_qty_rate('Purchase Order', trans_item, po.name) po.reload() - total_reqd_qty_after_change = sum([d.get("required_qty") for d in po.as_dict().get("supplied_items")]) + total_reqd_qty_after_change = sum(d.get("required_qty") for d in po.as_dict().get("supplied_items")) self.assertEqual(total_reqd_qty_after_change, 2 * total_reqd_qty) diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py index 180ba936661..0127eb81630 100644 --- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py +++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py @@ -391,7 +391,7 @@ def get_item_from_material_requests_based_on_supplier(source_name, target_doc = def get_supplier_tag(): if not frappe.cache().hget("Supplier", "Tags"): filters = {"document_type": "Supplier"} - tags = list(set([tag.tag for tag in frappe.get_all("Tag Link", filters=filters, fields=["tag"]) if tag])) + tags = list(set(tag.tag for tag in frappe.get_all("Tag Link", filters=filters, fields=["tag"]) if tag)) frappe.cache().hset("Supplier", "Tags", tags) return frappe.cache().hget("Supplier", "Tags") diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index f88e8df7286..2fdc19e315a 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -608,8 +608,8 @@ class AccountsController(TransactionBase): order_field = "purchase_order" order_doctype = "Purchase Order" - order_list = list(set([d.get(order_field) - for d in self.get("items") if d.get(order_field)])) + order_list = list(set(d.get(order_field) + for d in self.get("items") if d.get(order_field))) journal_entries = get_advance_journal_entries(party_type, party, party_account, amount_field, order_doctype, order_list, include_unallocated) @@ -633,8 +633,8 @@ class AccountsController(TransactionBase): def validate_advance_entries(self): order_field = "sales_order" if self.doctype == "Sales Invoice" else "purchase_order" - order_list = list(set([d.get(order_field) - for d in self.get("items") if d.get(order_field)])) + order_list = list(set(d.get(order_field) + for d in self.get("items") if d.get(order_field))) if not order_list: return diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index 3f2d3390c05..da819119b10 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -181,8 +181,8 @@ class BuyingController(StockController): stock_and_asset_items_amount += flt(d.base_net_amount) last_item_idx = d.idx - total_valuation_amount = sum([flt(d.base_tax_amount_after_discount_amount) for d in self.get("taxes") - if d.category in ["Valuation", "Valuation and Total"]]) + total_valuation_amount = sum(flt(d.base_tax_amount_after_discount_amount) for d in self.get("taxes") + if d.category in ["Valuation", "Valuation and Total"]) valuation_amount_adjustment = total_valuation_amount for i, item in enumerate(self.get("items")): @@ -325,7 +325,7 @@ class BuyingController(StockController): def update_raw_materials_supplied_based_on_stock_entries(self): self.set('supplied_items', []) - purchase_orders = set([d.purchase_order for d in self.items]) + purchase_orders = set(d.purchase_order for d in self.items) # qty of raw materials backflushed (for each item per purchase order) backflushed_raw_materials_map = get_backflushed_subcontracted_raw_materials(purchase_orders) diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py index 81ac234e700..7bd739a6ad3 100644 --- a/erpnext/controllers/queries.py +++ b/erpnext/controllers/queries.py @@ -88,7 +88,7 @@ def customer_query(doctype, txt, searchfield, start, page_len, filters): fields = get_fields("Customer", fields) searchfields = frappe.get_meta("Customer").get_search_fields() - searchfields = " or ".join([field + " like %(txt)s" for field in searchfields]) + searchfields = " or ".join(field + " like %(txt)s" for field in searchfields) return frappe.db.sql("""select {fields} from `tabCustomer` where docstatus < 2 diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py index 54156f379c5..7f28289760c 100644 --- a/erpnext/controllers/selling_controller.py +++ b/erpnext/controllers/selling_controller.py @@ -428,7 +428,7 @@ class SellingController(StockController): self.po_no = ', '.join(list(set(x.strip() for x in ','.join(po_nos).split(',')))) def get_po_nos(self, ref_doctype, ref_fieldname, po_nos): - doc_list = list(set([d.get(ref_fieldname) for d in self.items if d.get(ref_fieldname)])) + doc_list = list(set(d.get(ref_fieldname) for d in self.items if d.get(ref_fieldname))) if doc_list: po_nos += [d.po_no for d in frappe.get_all(ref_doctype, 'po_no', filters = {'name': ('in', doc_list)}) if d.get('po_no')] diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py index 83d4c331401..943f7aaeb12 100644 --- a/erpnext/controllers/status_updater.py +++ b/erpnext/controllers/status_updater.py @@ -299,8 +299,8 @@ class StatusUpdater(Document): args['name'] = self.get(args['percent_join_field_parent']) self._update_percent_field(args, update_modified) else: - distinct_transactions = set([d.get(args['percent_join_field']) - for d in self.get_all_children(args['source_dt'])]) + distinct_transactions = set(d.get(args['percent_join_field']) + for d in self.get_all_children(args['source_dt'])) for name in distinct_transactions: if name: diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py index 41ca404d9b8..71bde7fad73 100644 --- a/erpnext/controllers/stock_controller.py +++ b/erpnext/controllers/stock_controller.py @@ -310,7 +310,7 @@ class StockController(AccountsController): def get_serialized_items(self): serialized_items = [] - item_codes = list(set([d.item_code for d in self.get("items")])) + item_codes = list(set(d.item_code for d in self.get("items"))) if item_codes: serialized_items = frappe.db.sql_list("""select name from `tabItem` where has_serial_no=1 and name in ({})""".format(", ".join(["%s"]*len(item_codes))), @@ -321,8 +321,8 @@ class StockController(AccountsController): def validate_warehouse(self): from erpnext.stock.utils import validate_warehouse_company, validate_disabled_warehouse - warehouses = list(set([d.warehouse for d in - self.get("items") if getattr(d, "warehouse", None)])) + warehouses = list(set(d.warehouse for d in + self.get("items") if getattr(d, "warehouse", None))) target_warehouses = list(set([d.target_warehouse for d in self.get("items") if getattr(d, "target_warehouse", None)])) diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py index 9fae49482dd..dda642a5323 100644 --- a/erpnext/controllers/taxes_and_totals.py +++ b/erpnext/controllers/taxes_and_totals.py @@ -375,10 +375,10 @@ class calculate_taxes_and_totals(object): def manipulate_grand_total_for_inclusive_tax(self): # if fully inclusive taxes and diff - if self.doc.get("taxes") and any([cint(t.included_in_print_rate) for t in self.doc.get("taxes")]): + if self.doc.get("taxes") and any(cint(t.included_in_print_rate) for t in self.doc.get("taxes")): last_tax = self.doc.get("taxes")[-1] - non_inclusive_tax_amount = sum([flt(d.tax_amount_after_discount_amount) - for d in self.doc.get("taxes") if not d.included_in_print_rate]) + non_inclusive_tax_amount = sum(flt(d.tax_amount_after_discount_amount) + for d in self.doc.get("taxes") if not d.included_in_print_rate) diff = self.doc.total + non_inclusive_tax_amount \ - flt(last_tax.total, last_tax.precision("total")) @@ -518,8 +518,8 @@ class calculate_taxes_and_totals(object): def calculate_total_advance(self): if self.doc.docstatus < 2: - total_allocated_amount = sum([flt(adv.allocated_amount, adv.precision("allocated_amount")) - for adv in self.doc.get("advances")]) + total_allocated_amount = sum(flt(adv.allocated_amount, adv.precision("allocated_amount")) + for adv in self.doc.get("advances")) self.doc.total_advance = flt(total_allocated_amount, self.doc.precision("total_advance")) @@ -619,7 +619,7 @@ class calculate_taxes_and_totals(object): if self.doc.doctype == "Sales Invoice" \ and self.doc.paid_amount > self.doc.grand_total and not self.doc.is_return \ - and any([d.type == "Cash" for d in self.doc.payments]): + and any(d.type == "Cash" for d in self.doc.payments): grand_total = self.doc.rounded_total or self.doc.grand_total base_grand_total = self.doc.base_rounded_total or self.doc.base_grand_total diff --git a/erpnext/controllers/tests/test_mapper.py b/erpnext/controllers/tests/test_mapper.py index 66459fdbf8a..7a4b2d36148 100644 --- a/erpnext/controllers/tests/test_mapper.py +++ b/erpnext/controllers/tests/test_mapper.py @@ -26,8 +26,8 @@ class TestMapper(unittest.TestCase): # Assert that all inserted items are present in updated sales order src_items = item_list_1 + item_list_2 + item_list_3 - self.assertEqual(set([d for d in src_items]), - set([d.item_code for d in updated_so.items])) + self.assertEqual(set(d for d in src_items), + set(d.item_code for d in updated_so.items)) def make_quotation(self, item_list, customer): diff --git a/erpnext/controllers/website_list_for_contact.py b/erpnext/controllers/website_list_for_contact.py index ecf041efd17..7c072e4fad3 100644 --- a/erpnext/controllers/website_list_for_contact.py +++ b/erpnext/controllers/website_list_for_contact.py @@ -113,7 +113,7 @@ def post_process(doctype, data): doc.set_indicator() doc.status_display = ", ".join(doc.status_display) - doc.items_preview = ", ".join([d.item_name for d in doc.items if d.item_name]) + doc.items_preview = ", ".join(d.item_name for d in doc.items if d.item_name) result.append(doc) return result diff --git a/erpnext/manufacturing/doctype/job_card/job_card.py b/erpnext/manufacturing/doctype/job_card/job_card.py index d764db33f86..cdc45188942 100644 --- a/erpnext/manufacturing/doctype/job_card/job_card.py +++ b/erpnext/manufacturing/doctype/job_card/job_card.py @@ -317,7 +317,7 @@ class JobCard(Document): 'docstatus': ('!=', 2)}, fields = 'sum(transferred_qty) as qty', group_by='operation_id') if job_cards: - qty = min([d.qty for d in job_cards]) + qty = min(d.qty for d in job_cards) doc.db_set('material_transferred_for_manufacturing', qty) diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py index d1583f1473c..39a6024e2cc 100755 --- a/erpnext/projects/doctype/task/task.py +++ b/erpnext/projects/doctype/task/task.py @@ -232,7 +232,7 @@ def get_project(doctype, txt, searchfield, start, page_len, filters): meta = frappe.get_meta(doctype) searchfields = meta.get_search_fields() search_columns = ", " + ", ".join(searchfields) if searchfields else '' - search_cond = " or " + " or ".join([field + " like %(txt)s" for field in searchfields]) + search_cond = " or " + " or ".join(field + " like %(txt)s" for field in searchfields) return frappe.db.sql(""" select name {search_columns} from `tabProject` where %(key)s like %(txt)s diff --git a/erpnext/projects/doctype/timesheet/timesheet.py b/erpnext/projects/doctype/timesheet/timesheet.py index a3e4577f909..c8bd80fca0a 100644 --- a/erpnext/projects/doctype/timesheet/timesheet.py +++ b/erpnext/projects/doctype/timesheet/timesheet.py @@ -87,8 +87,8 @@ class Timesheet(Document): def set_dates(self): if self.docstatus < 2 and self.time_logs: - start_date = min([getdate(d.from_time) for d in self.time_logs]) - end_date = max([getdate(d.to_time) for d in self.time_logs]) + start_date = min(getdate(d.from_time) for d in self.time_logs) + end_date = max(getdate(d.to_time) for d in self.time_logs) if start_date and end_date: self.start_date = getdate(start_date) diff --git a/erpnext/projects/report/project_summary/project_summary.py b/erpnext/projects/report/project_summary/project_summary.py index 2c7bb49cfba..98dd617f9b3 100644 --- a/erpnext/projects/report/project_summary/project_summary.py +++ b/erpnext/projects/report/project_summary/project_summary.py @@ -122,7 +122,7 @@ def get_report_summary(data): if not data: return None - avg_completion = sum([project.percent_complete for project in data]) / len(data) + avg_completion = sum(project.percent_complete for project in data) / len(data) total = sum([project.total_tasks for project in data]) total_overdue = sum([project.overdue_tasks for project in data]) completed = sum([project.completed_tasks for project in data]) diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py index 51d86ff0bf8..818888c0c12 100644 --- a/erpnext/selling/doctype/customer/customer.py +++ b/erpnext/selling/doctype/customer/customer.py @@ -75,7 +75,7 @@ class Customer(TransactionBase): self.loyalty_program_tier = customer.loyalty_program_tier if self.sales_team: - if sum([member.allocated_percentage or 0 for member in self.sales_team]) != 100: + if sum(member.allocated_percentage or 0 for member in self.sales_team) != 100: frappe.throw(_("Total contribution percentage should be equal to 100")) def check_customer_group_change(self): diff --git a/erpnext/selling/doctype/quotation/quotation.py b/erpnext/selling/doctype/quotation/quotation.py index 246f9234a41..e4f8a475816 100644 --- a/erpnext/selling/doctype/quotation/quotation.py +++ b/erpnext/selling/doctype/quotation/quotation.py @@ -50,7 +50,7 @@ class Quotation(SellingController): self.customer_name = company_name or lead_name def update_opportunity(self, status): - for opportunity in list(set([d.prevdoc_docname for d in self.get("items")])): + for opportunity in set(d.prevdoc_docname for d in self.get("items")): if opportunity: self.update_opportunity_status(status, opportunity) diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index d9e52e1d69d..551f715bd52 100755 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -151,7 +151,7 @@ class SalesOrder(SellingController): frappe.db.sql("update `tabOpportunity` set status = %s where name=%s",(flag,enq[0][0])) def update_prevdoc_status(self, flag=None): - for quotation in list(set([d.prevdoc_docname for d in self.get("items")])): + for quotation in set(d.prevdoc_docname for d in self.get("items")): if quotation: doc = frappe.get_doc("Quotation", quotation) if doc.docstatus==2: diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py index 077538d479c..27e023c1e5b 100644 --- a/erpnext/setup/doctype/company/company.py +++ b/erpnext/setup/doctype/company/company.py @@ -54,7 +54,7 @@ class Company(NestedSet): def validate_abbr(self): if not self.abbr: - self.abbr = ''.join([c[0] for c in self.company_name.split()]).upper() + self.abbr = ''.join(c[0] for c in self.company_name.split()).upper() self.abbr = self.abbr.strip() @@ -335,7 +335,7 @@ class Company(NestedSet): clear_defaults_cache() def abbreviate(self): - self.abbr = ''.join([c[0].upper() for c in self.company_name.split()]) + self.abbr = ''.join(c[0].upper() for c in self.company_name.split()) def on_trash(self): """ diff --git a/erpnext/setup/doctype/item_group/item_group.py b/erpnext/setup/doctype/item_group/item_group.py index bff806d5472..db31d6d6992 100644 --- a/erpnext/setup/doctype/item_group/item_group.py +++ b/erpnext/setup/doctype/item_group/item_group.py @@ -139,7 +139,7 @@ def get_product_list_for_group(product_group=None, start=0, limit=10, search=Non # return child item groups if the type is of "Is Group" return get_child_groups_for_list_in_html(item_group, start, limit, search) - child_groups = ", ".join([frappe.db.escape(i[0]) for i in get_child_groups(product_group)]) + child_groups = ", ".join(frappe.db.escape(i[0]) for i in get_child_groups(product_group)) # base query query = """select I.name, I.item_name, I.item_code, I.route, I.image, I.website_image, I.thumbnail, I.item_group, @@ -239,7 +239,7 @@ def get_item_for_list_in_html(context): return frappe.get_template(products_template).render(context) def get_group_item_count(item_group): - child_groups = ", ".join(['"' + i[0] + '"' for i in get_child_groups(item_group)]) + child_groups = ", ".join('"' + i[0] + '"' for i in get_child_groups(item_group)) return frappe.db.sql("""select count(*) from `tabItem` where docstatus = 0 and show_in_website = 1 and (item_group in (%s) diff --git a/erpnext/stock/doctype/batch/batch.py b/erpnext/stock/doctype/batch/batch.py index 8fdda565d20..508e17c3409 100644 --- a/erpnext/stock/doctype/batch/batch.py +++ b/erpnext/stock/doctype/batch/batch.py @@ -304,7 +304,7 @@ def validate_serial_no_with_batch(serial_nos, item_code): frappe.throw(_("The serial no {0} does not belong to item {1}") .format(get_link_to_form("Serial No", serial_nos[0]), get_link_to_form("Item", item_code))) - serial_no_link = ','.join([get_link_to_form("Serial No", sn) for sn in serial_nos]) + serial_no_link = ','.join(get_link_to_form("Serial No", sn) for sn in serial_nos) message = "Serial Nos" if len(serial_nos) > 1 else "Serial No" frappe.throw(_("There is no batch found against the {0}: {1}") diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py index cce51cb9b17..dd31965face 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/delivery_note.py @@ -264,7 +264,7 @@ class DeliveryNote(SellingController): """ Validate that if packed qty exists, it should be equal to qty """ - if not any([flt(d.get('packed_qty')) for d in self.get("items")]): + if not any(flt(d.get('packed_qty')) for d in self.get("items")): return has_error = False for d in self.get("items"): diff --git a/erpnext/stock/doctype/delivery_trip/delivery_trip.py b/erpnext/stock/doctype/delivery_trip/delivery_trip.py index 81e730126ec..9ec28d89814 100644 --- a/erpnext/stock/doctype/delivery_trip/delivery_trip.py +++ b/erpnext/stock/doctype/delivery_trip/delivery_trip.py @@ -68,7 +68,7 @@ class DeliveryTrip(Document): delete (bool, optional): Defaults to `False`. `True` if driver details need to be emptied, else `False`. """ - delivery_notes = list(set([stop.delivery_note for stop in self.delivery_stops if stop.delivery_note])) + delivery_notes = list(set(stop.delivery_note for stop in self.delivery_stops if stop.delivery_note)) update_fields = { "driver": self.driver, @@ -136,8 +136,8 @@ class DeliveryTrip(Document): # Include last leg in the final distance calculation self.uom = self.default_distance_uom - total_distance = sum([leg.get("distance", {}).get("value", 0.0) - for leg in directions.get("legs")]) # in meters + total_distance = sum(leg.get("distance", {}).get("value", 0.0) + for leg in directions.get("legs")) # in meters self.total_distance = total_distance * self.uom_conversion_factor else: idx += len(route) - 1 diff --git a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py index 83109469fc7..5df4d8743fc 100644 --- a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py +++ b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py @@ -78,7 +78,7 @@ class LandedCostVoucher(Document): .format(item.idx, item.item_code)) def set_total_taxes_and_charges(self): - self.total_taxes_and_charges = sum([flt(d.base_amount) for d in self.get("taxes")]) + self.total_taxes_and_charges = sum(flt(d.base_amount) for d in self.get("taxes")) def set_applicable_charges_on_item(self): if self.get('taxes') and self.distribute_charges_based_on != 'Distribute Manually': @@ -104,15 +104,15 @@ class LandedCostVoucher(Document): based_on = self.distribute_charges_based_on.lower() if based_on != 'distribute manually': - total = sum([flt(d.get(based_on)) for d in self.get("items")]) + total = sum(flt(d.get(based_on)) for d in self.get("items")) else: # consider for proportion while distributing manually - total = sum([flt(d.get('applicable_charges')) for d in self.get("items")]) + total = sum(flt(d.get('applicable_charges')) for d in self.get("items")) if not total: frappe.throw(_("Total {0} for all items is zero, may be you should change 'Distribute Charges Based On'").format(based_on)) - total_applicable_charges = sum([flt(d.applicable_charges) for d in self.get("items")]) + total_applicable_charges = sum(flt(d.applicable_charges) for d in self.get("items")) precision = get_field_precision(frappe.get_meta("Landed Cost Item").get_field("applicable_charges"), currency=frappe.get_cached_value('Company', self.company, "default_currency")) diff --git a/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py b/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py index 984ae46c66c..32b08f60c4a 100644 --- a/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py +++ b/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py @@ -311,7 +311,7 @@ def create_landed_cost_voucher(receipt_document_type, receipt_document, company, def distribute_landed_cost_on_items(lcv): based_on = lcv.distribute_charges_based_on.lower() - total = sum([flt(d.get(based_on)) for d in lcv.get("items")]) + total = sum(flt(d.get(based_on)) for d in lcv.get("items")) for item in lcv.get("items"): item.applicable_charges = flt(item.get(based_on)) * flt(lcv.total_taxes_and_charges) / flt(total) diff --git a/erpnext/stock/doctype/packing_slip/packing_slip.py b/erpnext/stock/doctype/packing_slip/packing_slip.py index 2008bffcd32..4a843e0fde9 100644 --- a/erpnext/stock/doctype/packing_slip/packing_slip.py +++ b/erpnext/stock/doctype/packing_slip/packing_slip.py @@ -88,9 +88,9 @@ class PackingSlip(Document): rows = [d.item_code for d in self.get("items")] # also pick custom fields from delivery note - custom_fields = ', '.join(['dni.`{0}`'.format(d.fieldname) + custom_fields = ', '.join('dni.`{0}`'.format(d.fieldname) for d in frappe.get_meta("Delivery Note Item").get_custom_fields() - if d.fieldtype not in no_value_fields]) + if d.fieldtype not in no_value_fields) if custom_fields: custom_fields = ', ' + custom_fields diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py index 5095a80214d..8d9b675bed3 100644 --- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py @@ -246,7 +246,7 @@ class TestPurchaseReceipt(unittest.TestCase): pr = make_purchase_receipt(item_code="_Test FG Item", qty=10, rate=500, is_subcontracted="Yes") self.assertEqual(len(pr.get("supplied_items")), 2) - rm_supp_cost = sum([d.amount for d in pr.get("supplied_items")]) + rm_supp_cost = sum(d.amount for d in pr.get("supplied_items")) self.assertEqual(pr.get("items")[0].rm_supp_cost, flt(rm_supp_cost, 2)) pr.cancel() diff --git a/erpnext/stock/doctype/serial_no/serial_no.py b/erpnext/stock/doctype/serial_no/serial_no.py index 5ecc9f81405..b236f6a9990 100644 --- a/erpnext/stock/doctype/serial_no/serial_no.py +++ b/erpnext/stock/doctype/serial_no/serial_no.py @@ -613,7 +613,7 @@ def fetch_serial_numbers(filters, qty, do_not_include=[]): batch_nos = filters.get("batch_no") expiry_date = filters.get("expiry_date") if batch_nos: - batch_no_condition = """and sr.batch_no in ({}) """.format(', '.join(["'%s'" % d for d in batch_nos])) + batch_no_condition = """and sr.batch_no in ({}) """.format(', '.join("'%s'" % d for d in batch_nos)) if expiry_date: batch_join_selection = "LEFT JOIN `tabBatch` batch on sr.batch_no = batch.name " diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 2f76bc7d56a..560ceaa917b 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -465,7 +465,7 @@ class StockEntry(StockController): """ # Set rate for outgoing items outgoing_items_cost = self.set_rate_for_outgoing_items(reset_outgoing_rate, raise_error_if_no_rate) - finished_item_qty = sum([d.transfer_qty for d in self.items if d.is_finished_item]) + finished_item_qty = sum(d.transfer_qty for d in self.items if d.is_finished_item) # Set basic rate for incoming items for d in self.get('items'): diff --git a/erpnext/stock/report/item_price_stock/item_price_stock.py b/erpnext/stock/report/item_price_stock/item_price_stock.py index 5296211fae8..db7498bb215 100644 --- a/erpnext/stock/report/item_price_stock/item_price_stock.py +++ b/erpnext/stock/report/item_price_stock/item_price_stock.py @@ -89,7 +89,7 @@ def get_item_price_qty_data(filters): {conditions}""" .format(conditions=conditions), filters, as_dict=1) - price_list_names = list(set([item.price_list_name for item in item_results])) + price_list_names = list(set(item.price_list_name for item in item_results)) buying_price_map = get_price_map(price_list_names, buying=1) selling_price_map = get_price_map(price_list_names, selling=1) 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 2f70523264a..2e13aa0b040 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 @@ -66,7 +66,7 @@ def get_consumed_items(condition): purpose is NULL or purpose not in ({}) ) - """.format(', '.join([f"'{p}'" for p in purpose_to_exclude])) + """.format(', '.join(f"'{p}'" for p in purpose_to_exclude)) condition = condition.replace("posting_date", "sle.posting_date") consumed_items = frappe.db.sql(""" diff --git a/erpnext/stock/report/product_bundle_balance/product_bundle_balance.py b/erpnext/stock/report/product_bundle_balance/product_bundle_balance.py index 276e42ee433..8fffbccab3c 100644 --- a/erpnext/stock/report/product_bundle_balance/product_bundle_balance.py +++ b/erpnext/stock/report/product_bundle_balance/product_bundle_balance.py @@ -141,7 +141,7 @@ def get_stock_ledger_entries(filters, items): return [] item_conditions_sql = ' and sle.item_code in ({})' \ - .format(', '.join([frappe.db.escape(i) for i in items])) + .format(', '.join(frappe.db.escape(i) for i in items)) conditions = get_sle_conditions(filters) diff --git a/erpnext/stock/report/stock_balance/stock_balance.py b/erpnext/stock/report/stock_balance/stock_balance.py index bbd73e91129..b6a80631892 100644 --- a/erpnext/stock/report/stock_balance/stock_balance.py +++ b/erpnext/stock/report/stock_balance/stock_balance.py @@ -157,7 +157,7 @@ def get_stock_ledger_entries(filters, items): item_conditions_sql = '' if items: item_conditions_sql = ' and sle.item_code in ({})'\ - .format(', '.join([frappe.db.escape(i, percent=False) for i in items])) + .format(', '.join(frappe.db.escape(i, percent=False) for i in items)) conditions = get_conditions(filters) @@ -253,7 +253,7 @@ def get_items(filters): def get_item_details(items, sle, filters): item_details = {} if not items: - items = list(set([d.item_code for d in sle])) + items = list(set(d.item_code for d in sle)) if not items: return item_details @@ -291,7 +291,7 @@ def get_item_reorder_details(items): select parent, warehouse, warehouse_reorder_qty, warehouse_reorder_level from `tabItem Reorder` where parent in ({0}) - """.format(', '.join([frappe.db.escape(i, percent=False) for i in items])), as_dict=1) + """.format(', '.join(frappe.db.escape(i, percent=False) for i in items)), as_dict=1) return dict((d.parent + d.warehouse, d) for d in item_reorder_details) diff --git a/erpnext/stock/report/stock_ledger/stock_ledger.py b/erpnext/stock/report/stock_ledger/stock_ledger.py index 36996e96745..8909f217f49 100644 --- a/erpnext/stock/report/stock_ledger/stock_ledger.py +++ b/erpnext/stock/report/stock_ledger/stock_ledger.py @@ -115,7 +115,7 @@ def get_stock_ledger_entries(filters, items): item_conditions_sql = '' if items: item_conditions_sql = 'and sle.item_code in ({})'\ - .format(', '.join([frappe.db.escape(i) for i in items])) + .format(', '.join(frappe.db.escape(i) for i in items)) sl_entries = frappe.db.sql(""" SELECT @@ -169,7 +169,7 @@ def get_items(filters): def get_item_details(items, sl_entries, include_uom): item_details = {} if not items: - items = list(set([d.item_code for d in sl_entries])) + items = list(set(d.item_code for d in sl_entries)) if not items: return item_details diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py index b2825fc26f5..fc82c789cc7 100644 --- a/erpnext/stock/stock_ledger.py +++ b/erpnext/stock/stock_ledger.py @@ -521,7 +521,7 @@ class update_entries_after(object): fields=["purchase_rate", "name", "company"], filters = {'name': ('in', serial_nos)}) - incoming_values = sum([flt(d.purchase_rate) for d in all_serial_nos if d.company==sle.company]) + incoming_values = sum(flt(d.purchase_rate) for d in all_serial_nos if d.company==sle.company) # Get rate for serial nos which has been transferred to other company invalid_serial_nos = [d.name for d in all_serial_nos if d.company!=sle.company] diff --git a/erpnext/support/doctype/warranty_claim/warranty_claim.py b/erpnext/support/doctype/warranty_claim/warranty_claim.py index a3428a25af4..a20e7a801b0 100644 --- a/erpnext/support/doctype/warranty_claim/warranty_claim.py +++ b/erpnext/support/doctype/warranty_claim/warranty_claim.py @@ -29,7 +29,7 @@ class WarrantyClaim(TransactionBase): where t2.parent = t1.name and t2.prevdoc_docname = %s and t1.docstatus!=2""", (self.name)) if lst: - lst1 = ','.join([x[0] for x in lst]) + lst1 = ','.join(x[0] for x in lst) frappe.throw(_("Cancel Material Visit {0} before cancelling this Warranty Claim").format(lst1)) else: frappe.db.set(self, 'status', 'Cancelled') diff --git a/erpnext/utilities/product.py b/erpnext/utilities/product.py index 66d6cd38886..70b41767d6d 100644 --- a/erpnext/utilities/product.py +++ b/erpnext/utilities/product.py @@ -131,6 +131,6 @@ def get_non_stock_item_status(item_code, item_warehouse_field): if frappe.db.exists("Product Bundle", item_code): items = frappe.get_doc("Product Bundle", item_code).get_all_children() bundle_warehouse = frappe.db.get_value('Item', item_code, item_warehouse_field) - return all([ get_qty_in_stock(d.item_code, item_warehouse_field, bundle_warehouse).in_stock for d in items ]) + return all(get_qty_in_stock(d.item_code, item_warehouse_field, bundle_warehouse).in_stock for d in items) else: return 1 diff --git a/erpnext/utilities/transaction_base.py b/erpnext/utilities/transaction_base.py index f99da58e467..db997263c1a 100644 --- a/erpnext/utilities/transaction_base.py +++ b/erpnext/utilities/transaction_base.py @@ -147,7 +147,7 @@ class TransactionBase(StatusUpdater): if hasattr(self, "prev_link_mapper") and self.prev_link_mapper.get(for_doctype): fieldname = self.prev_link_mapper[for_doctype]["fieldname"] - values = filter(None, tuple([item.as_dict()[fieldname] for item in self.items])) + values = filter(None, tuple(item.as_dict()[fieldname] for item in self.items)) if values: ret = { @@ -180,7 +180,7 @@ def validate_uom_is_integer(doc, uom_field, qty_fields, child_dt=None): if isinstance(qty_fields, string_types): qty_fields = [qty_fields] - distinct_uoms = list(set([d.get(uom_field) for d in doc.get_all_children()])) + distinct_uoms = list(set(d.get(uom_field) for d in doc.get_all_children())) integer_uoms = list(filter(lambda uom: frappe.db.get_value("UOM", uom, "must_be_whole_number", cache=True) or None, distinct_uoms)) From 348f04ca82635373935df6b28e3203e85f7d1e1a Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Fri, 11 Jun 2021 21:01:30 +0530 Subject: [PATCH 134/135] fix: syntax error in serial/batch selector (#26024) --- erpnext/public/js/utils/serial_no_batch_selector.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/public/js/utils/serial_no_batch_selector.js b/erpnext/public/js/utils/serial_no_batch_selector.js index 02b5ef39307..597d77c6e9f 100644 --- a/erpnext/public/js/utils/serial_no_batch_selector.js +++ b/erpnext/public/js/utils/serial_no_batch_selector.js @@ -324,7 +324,7 @@ erpnext.SerialNoBatchSelector = class SerialNoBatchSelector { qty_field.set_input(total_qty); } - update_pending_qtys: function() { + update_pending_qtys() { const pending_qty_field = this.dialog.fields_dict.pending_qty; const total_selected_qty_field = this.dialog.fields_dict.total_selected_qty; @@ -340,7 +340,7 @@ erpnext.SerialNoBatchSelector = class SerialNoBatchSelector { total_selected_qty_field.set_input(total_selected_qty); } - get_batch_fields: function() { + get_batch_fields() { var me = this; return [ @@ -537,7 +537,7 @@ erpnext.SerialNoBatchSelector = class SerialNoBatchSelector { } ]; } -}); +}; function get_pending_qty_fields(me) { if (!check_can_calculate_pending_qty(me)) return []; From 0ed33aa4e8fa3efc98e66bd061755dcca8715d2e Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Sat, 12 Jun 2021 13:40:58 +0530 Subject: [PATCH 135/135] fix: unable to enter score in Assessment Result details grid (#25945) --- .../education/doctype/assessment_result/assessment_result.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/education/doctype/assessment_result/assessment_result.js b/erpnext/education/doctype/assessment_result/assessment_result.js index 617a873b820..c35f607a99d 100644 --- a/erpnext/education/doctype/assessment_result/assessment_result.js +++ b/erpnext/education/doctype/assessment_result/assessment_result.js @@ -6,7 +6,8 @@ frappe.ui.form.on('Assessment Result', { if (!frm.doc.__islocal) { frm.trigger('setup_chart'); } - frm.set_df_property('details', 'read_only', 1); + + frm.get_field('details').grid.cannot_add_rows = true; frm.set_query('course', function() { return {