Merge branch 'develop' into fixing-emp-contacts

This commit is contained in:
Abdeali Chharchhoda
2026-01-19 17:55:55 +05:30
986 changed files with 241125 additions and 356239 deletions

View File

@@ -1,6 +1,5 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
import unittest
from frappe.tests import IntegrationTestCase

View File

@@ -1,4 +1,3 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
import frappe

View File

@@ -2,8 +2,6 @@
# License: GNU General Public License v3. See license.txt
import copy
import frappe
from frappe.model.document import Document

View File

@@ -1,4 +1,3 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
import frappe

View File

@@ -40,6 +40,13 @@ frappe.ui.form.on("Company", {
return { filters: { selling: 1 } };
});
frm.set_query("default_sales_contact", function (doc) {
return {
query: "frappe.contacts.doctype.contact.contact.contact_query",
filters: { link_doctype: "Company", link_name: doc.name },
};
});
frm.set_query("default_buying_terms", function () {
return { filters: { buying: 1 } };
});
@@ -53,6 +60,15 @@ frappe.ui.form.on("Company", {
},
};
});
frm.set_query("default_warehouse_for_sales_return", function () {
return {
filters: {
company: frm.doc.name,
is_group: 0,
},
};
});
},
company_name: function (frm) {
@@ -241,7 +257,7 @@ erpnext.company.set_chart_of_accounts_options = function (doc) {
callback: function (r) {
if (!r.exc) {
set_field_options("chart_of_accounts", [""].concat(r.message).join("\n"));
if (in_list(r.message, selected_value))
if (r.message.includes(selected_value))
cur_frm.set_value("chart_of_accounts", selected_value);
}
},
@@ -258,7 +274,7 @@ erpnext.company.setup_queries = function (frm) {
["default_payable_account", { root_type: "Liability", account_type: "Payable" }],
["default_expense_account", { root_type: "Expense" }],
["default_income_account", { root_type: "Income" }],
["round_off_account", { root_type: "Expense" }],
["round_off_account", { root_type: ["in", ["Expense", "Income"]] }],
["round_off_for_opening", { root_type: "Liability", account_type: "Round Off for Opening" }],
["write_off_account", { root_type: "Expense" }],
["default_deferred_expense_account", {}],

View File

@@ -95,6 +95,11 @@
"depreciation_cost_center",
"capital_work_in_progress_account",
"asset_received_but_not_billed",
"accounts_closing_tab",
"accounts_closing_section",
"accounts_frozen_till_date",
"column_break_tawz",
"role_allowed_for_frozen_entries",
"buying_and_selling_tab",
"sales_settings",
"default_buying_terms",
@@ -103,6 +108,7 @@
"total_monthly_sales",
"column_break_goals",
"default_selling_terms",
"default_sales_contact",
"default_warehouse_for_sales_return",
"credit_limit",
"transactions_annual_history",
@@ -117,6 +123,7 @@
"enable_item_wise_inventory_account",
"enable_provisional_accounting_for_non_stock_items",
"default_inventory_account",
"valuation_method",
"column_break_32",
"stock_adjustment_account",
"stock_received_but_not_billed",
@@ -124,6 +131,10 @@
"default_in_transit_warehouse",
"manufacturing_section",
"default_operating_cost_account",
"column_break_9prc",
"default_wip_warehouse",
"default_fg_warehouse",
"default_scrap_warehouse",
"dashboard_tab"
],
"fields": [
@@ -885,14 +896,81 @@
"fieldname": "enable_item_wise_inventory_account",
"fieldtype": "Check",
"label": "Enable Item-wise Inventory Account"
},
{
"default": "FIFO",
"fieldname": "valuation_method",
"fieldtype": "Select",
"label": "Default Stock Valuation Method",
"options": "FIFO\nMoving Average\nLIFO",
"reqd": 1
},
{
"fieldname": "default_wip_warehouse",
"fieldtype": "Link",
"label": " Default Work In Progress Warehouse ",
"link_filters": "[[\"Warehouse\",\"disabled\",\"=\",0]]",
"options": "Warehouse"
},
{
"fieldname": "default_fg_warehouse",
"fieldtype": "Link",
"label": "Default Finished Goods Warehouse",
"link_filters": "[[\"Warehouse\",\"disabled\",\"=\",0]]",
"options": "Warehouse"
},
{
"fieldname": "default_scrap_warehouse",
"fieldtype": "Link",
"label": "Default Scrap Warehouse",
"link_filters": "[[\"Warehouse\",\"disabled\",\"=\",0]]",
"options": "Warehouse"
},
{
"fieldname": "column_break_9prc",
"fieldtype": "Column Break"
},
{
"fieldname": "default_sales_contact",
"fieldtype": "Link",
"label": "Default Sales Contact",
"options": "Contact"
},
{
"description": "Accounting entries are frozen up to this date. Only users with the specified role can create or modify entries before this date.",
"fieldname": "accounts_frozen_till_date",
"fieldtype": "Date",
"in_list_view": 1,
"label": "Accounts Frozen Till Date"
},
{
"fieldname": "accounts_closing_tab",
"fieldtype": "Tab Break",
"label": "Accounts Closing"
},
{
"fieldname": "column_break_tawz",
"fieldtype": "Column Break"
},
{
"fieldname": "role_allowed_for_frozen_entries",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Roles Allowed to Set and Edit Frozen Account Entries",
"options": "Role"
},
{
"fieldname": "accounts_closing_section",
"fieldtype": "Section Break"
}
],
"grid_page_length": 50,
"icon": "fa fa-building",
"idx": 1,
"image_field": "company_logo",
"is_tree": 1,
"links": [],
"modified": "2025-10-23 13:15:52.411984",
"modified": "2025-11-16 16:51:27.624096",
"modified_by": "Administrator",
"module": "Setup",
"name": "Company",

View File

@@ -11,11 +11,22 @@ from frappe.cache_manager import clear_defaults_cache
from frappe.contacts.address_and_contact import load_address_and_contact
from frappe.custom.doctype.property_setter.property_setter import make_property_setter
from frappe.desk.page.setup_wizard.setup_wizard import make_records
from frappe.utils import add_months, cint, formatdate, get_first_day, get_link_to_form, get_timestamp, today
from frappe.utils import (
cint,
get_first_day,
get_last_day,
get_link_to_form,
get_timestamp,
today,
)
from frappe.utils.nestedset import NestedSet, rebuild_tree
from erpnext.accounts.doctype.account.account import get_account_currency
from erpnext.accounts.doctype.financial_report_template.financial_report_template import (
sync_financial_report_templates,
)
from erpnext.setup.setup_wizard.operations.taxes_setup import setup_taxes_and_charges
from erpnext.stock.utils import check_pending_reposting
class Company(NestedSet):
@@ -28,6 +39,7 @@ class Company(NestedSet):
from frappe.types import DF
abbr: DF.Data
accounts_frozen_till_date: DF.Date | None
accumulated_depreciation_account: DF.Link | None
allow_account_creation_against_child_company: DF.Check
asset_received_but_not_billed: DF.Link | None
@@ -56,6 +68,7 @@ class Company(NestedSet):
default_deferred_revenue_account: DF.Link | None
default_discount_account: DF.Link | None
default_expense_account: DF.Link | None
default_fg_warehouse: DF.Link | None
default_finance_book: DF.Link | None
default_holiday_list: DF.Link | None
default_in_transit_warehouse: DF.Link | None
@@ -66,8 +79,11 @@ class Company(NestedSet):
default_payable_account: DF.Link | None
default_provisional_account: DF.Link | None
default_receivable_account: DF.Link | None
default_sales_contact: DF.Link | None
default_scrap_warehouse: DF.Link | None
default_selling_terms: DF.Link | None
default_warehouse_for_sales_return: DF.Link | None
default_wip_warehouse: DF.Link | None
depreciation_cost_center: DF.Link | None
depreciation_expense_account: DF.Link | None
disposal_account: DF.Link | None
@@ -96,6 +112,7 @@ class Company(NestedSet):
registration_details: DF.Code | None
reporting_currency: DF.Link | None
rgt: DF.Int
role_allowed_for_frozen_entries: DF.Link | None
round_off_account: DF.Link | None
round_off_cost_center: DF.Link | None
round_off_for_opening: DF.Link | None
@@ -110,6 +127,7 @@ class Company(NestedSet):
transactions_annual_history: DF.Code | None
unrealized_exchange_gain_loss_account: DF.Link | None
unrealized_profit_loss_account: DF.Link | None
valuation_method: DF.Literal["FIFO", "Moving Average", "LIFO"]
website: DF.Data | None
write_off_account: DF.Link | None
# end: auto-generated types
@@ -143,6 +161,7 @@ class Company(NestedSet):
return exists
def validate(self):
old_doc = self.get_doc_before_save()
self.update_default_account = False
if self.is_new():
self.update_default_account = True
@@ -160,6 +179,33 @@ class Company(NestedSet):
self.validate_parent_company()
self.set_reporting_currency()
self.validate_inventory_account_settings()
self.cant_change_valuation_method()
self.validate_pending_reposts(old_doc)
def cant_change_valuation_method(self):
doc_before_save = self.get_doc_before_save()
if not doc_before_save:
return
previous_valuation_method = doc_before_save.get("valuation_method")
if previous_valuation_method and previous_valuation_method != self.valuation_method:
# check if there are any stock ledger entries against items
# which does not have it's own valuation method
sle = frappe.db.sql(
"""select name from `tabStock Ledger Entry` sle
where exists(select name from tabItem
where name=sle.item_code and (valuation_method is null or valuation_method='')) and sle.company=%s limit 1
""",
self.name,
)
if sle:
frappe.throw(
_(
"Can't change the valuation method, as there are transactions against some items which do not have its own valuation method"
)
)
def validate_inventory_account_settings(self):
doc_before_save = self.get_doc_before_save()
@@ -294,6 +340,7 @@ class Company(NestedSet):
):
if not frappe.local.flags.ignore_chart_of_accounts:
frappe.flags.country_change = True
sync_financial_report_templates(self.chart_of_accounts, self.existing_company)
self.create_default_accounts()
self.create_default_warehouses()
@@ -562,6 +609,11 @@ class Company(NestedSet):
)
self.reporting_currency = parent_reporting_currency
def validate_pending_reposts(self, old_doc):
if old_doc and old_doc.accounts_frozen_till_date != self.accounts_frozen_till_date:
if self.accounts_frozen_till_date:
check_pending_reposting(self.accounts_frozen_till_date, self.name)
def set_default_accounts(self):
default_accounts = {
"default_cash_account": "Cash",
@@ -821,31 +873,41 @@ def install_country_fixtures(company, country):
def update_company_current_month_sales(company):
from_date = get_first_day(today())
to_date = get_first_day(add_months(from_date, 1))
"""Update Company's Total Monthly Sales.
results = frappe.db.sql(
"""
SELECT
SUM(base_grand_total) AS total,
DATE_FORMAT(posting_date, '%%m-%%Y') AS month_year
FROM
`tabSales Invoice`
WHERE
posting_date >= %s
AND posting_date < %s
AND docstatus = 1
AND company = %s
GROUP BY
month_year
""",
(from_date, to_date, company),
as_dict=True,
Postgres compatibility:
- Avoid MariaDB-only DATE_FORMAT().
- Use a date range for the current month instead (portable + index-friendly).
"""
# Local imports so you don't have to touch file-level imports
from frappe.query_builder.functions import Sum
start_date = get_first_day(today())
end_date = get_last_day(today())
si = frappe.qb.DocType("Sales Invoice")
total_monthly_sales = (
frappe.qb.from_(si)
.select(Sum(si.base_grand_total))
.where(
(si.docstatus == 1)
& (si.company == company)
& (si.posting_date >= start_date)
& (si.posting_date <= end_date)
)
).run(pluck=True)[0] or 0
# Fieldname in standard ERPNext is `total_monthly_sales`
frappe.db.set_value(
"Company",
company,
"total_monthly_sales",
total_monthly_sales,
update_modified=False,
)
monthly_total = results[0]["total"] if len(results) > 0 else 0
frappe.db.set_value("Company", company, "total_monthly_sales", monthly_total)
def update_company_monthly_sales(company):
"""Cache past year monthly sales of every company based on sales invoices"""

View File

@@ -1,7 +1,6 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
import json
import unittest
import frappe
from frappe import _

View File

@@ -1,6 +1,5 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
import unittest
from unittest import mock
import frappe
@@ -66,9 +65,9 @@ def patched_requests_get(*args, **kwargs):
if kwargs["params"].get("date") and kwargs["params"].get("from") and kwargs["params"].get("to"):
if test_exchange_values.get(kwargs["params"]["date"]):
return PatchResponse({"result": test_exchange_values[kwargs["params"]["date"]]}, 200)
elif args[0].startswith("https://api.frankfurter.app") and kwargs.get("params"):
elif args[0].startswith("https://api.frankfurter.dev") and kwargs.get("params"):
if kwargs["params"].get("base") and kwargs["params"].get("symbols"):
date = args[0].replace("https://api.frankfurter.app/", "")
date = args[0].replace("https://api.frankfurter.dev/v1/", "")
if test_exchange_values.get(date):
return PatchResponse(
{"rates": {kwargs["params"].get("symbols"): test_exchange_values.get(date)}}, 200
@@ -147,7 +146,7 @@ class TestCurrencyExchange(IntegrationTestCase):
self.assertEqual(flt(exchange_rate, 3), 65.1)
settings = frappe.get_single("Currency Exchange Settings")
settings.service_provider = "frankfurter.app"
settings.service_provider = "frankfurter.dev"
settings.save()
def test_exchange_rate_strict(self, mock_get):

View File

@@ -140,7 +140,7 @@
"idx": 1,
"is_tree": 1,
"links": [],
"modified": "2025-01-22 10:48:10.186637",
"modified": "2025-12-02 13:58:03.378607",
"modified_by": "Administrator",
"module": "Setup",
"name": "Customer Group",
@@ -209,10 +209,11 @@
"share": 1
}
],
"row_format": "Dynamic",
"search_fields": "parent_customer_group",
"show_name_in_global_search": 1,
"sort_field": "creation",
"sort_order": "DESC",
"states": [],
"translated_doctype": 1
}
}

View File

@@ -2,4 +2,3 @@
# License: GNU General Public License v3. See license.txt
import frappe

View File

@@ -1,6 +1,5 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
import unittest
import frappe
from frappe.tests import IntegrationTestCase

View File

@@ -1,6 +1,5 @@
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
import unittest
from frappe.tests import IntegrationTestCase

View File

@@ -162,8 +162,6 @@ class EmailDigest(Document):
context.purchase_order_list,
context.purchase_orders_items_overdue_list,
) = self.get_purchase_orders_items_overdue_list()
if not context.purchase_order_list:
frappe.throw(_("No items to be received are overdue"))
if not context:
return None
@@ -799,7 +797,7 @@ class EmailDigest(Document):
"status": ["not in", ("Cancelled")],
"company": self.company,
},
fields=["count(*) as count", "sum(grand_total) as grand_total"],
fields=[{"COUNT": "*", "as": "count"}, {"SUM": "grand_total", "as": "grand_total"}],
)
def get_from_to_date(self):

View File

@@ -1,6 +1,5 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
import unittest
from frappe.tests import IntegrationTestCase

View File

@@ -11,7 +11,13 @@ erpnext.setup.EmployeeController = class EmployeeController extends frappe.ui.fo
};
};
this.frm.fields_dict.reports_to.get_query = function (doc, cdt, cdn) {
return { query: "erpnext.controllers.queries.employee_query" };
return {
query: "erpnext.controllers.queries.employee_query",
filters: [
["status", "=", "Active"],
["name", "!=", doc.name],
],
};
};
}

View File

@@ -253,7 +253,11 @@ def get_employee_email(employee_doc):
)
def get_holiday_list_for_employee(employee, raise_exception=True):
def get_holiday_list_for_employee(employee, raise_exception=True, as_on=None):
hrms_override = frappe.get_hooks("employee_holiday_list")
if hrms_override:
return frappe.get_attr(hrms_override[-1])(employee, raise_exception, as_on)
if employee:
holiday_list, company = frappe.get_cached_value("Employee", employee, ["holiday_list", "company"])
else:

View File

@@ -1,6 +1,5 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
import unittest
import frappe
import frappe.utils

View File

@@ -1,6 +1,5 @@
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
import unittest
import frappe
from frappe.tests import IntegrationTestCase

View File

@@ -82,12 +82,14 @@
"read_only": 1
}
],
"grid_page_length": 50,
"hide_toolbar": 1,
"icon": "fa fa-cog",
"idx": 1,
"in_create": 1,
"issingle": 1,
"links": [],
"modified": "2024-03-27 13:09:45.400219",
"modified": "2026-01-02 18:13:13.421866",
"modified_by": "Administrator",
"module": "Setup",
"name": "Global Defaults",
@@ -102,7 +104,8 @@
}
],
"read_only": 1,
"row_format": "Dynamic",
"sort_field": "creation",
"sort_order": "DESC",
"states": []
}
}

View File

@@ -1,6 +1,5 @@
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
import unittest
from frappe.tests import IntegrationTestCase

View File

@@ -10,10 +10,12 @@
"column_break_2",
"weekly_off",
"section_break_4",
"description"
"description",
"is_half_day"
],
"fields": [
{
"columns": 2,
"fieldname": "holiday_date",
"fieldtype": "Date",
"in_list_view": 1,
@@ -23,6 +25,7 @@
"reqd": 1
},
{
"columns": 3,
"fieldname": "description",
"fieldtype": "Text Editor",
"in_list_view": 1,
@@ -32,6 +35,7 @@
"width": "300px"
},
{
"columns": 2,
"default": "0",
"fieldname": "weekly_off",
"fieldtype": "Check",
@@ -44,18 +48,28 @@
{
"fieldname": "section_break_4",
"fieldtype": "Section Break"
},
{
"columns": 2,
"default": "0",
"fieldname": "is_half_day",
"fieldtype": "Check",
"in_list_view": 1,
"in_preview": 1,
"label": "Is Half Day"
}
],
"idx": 1,
"istable": 1,
"links": [],
"modified": "2024-03-27 13:09:49.810408",
"modified": "2025-08-28 15:15:44.177181",
"modified_by": "Administrator",
"module": "Setup",
"name": "Holiday",
"owner": "Administrator",
"permissions": [],
"row_format": "Dynamic",
"sort_field": "creation",
"sort_order": "ASC",
"states": []
}
}

View File

@@ -16,6 +16,7 @@ class Holiday(Document):
description: DF.TextEditor
holiday_date: DF.Date
is_half_day: DF.Check
parent: DF.Data
parentfield: DF.Data
parenttype: DF.Data

View File

@@ -16,6 +16,8 @@
"add_weekly_holidays",
"weekly_off",
"get_weekly_off_dates",
"column_break_euok",
"is_half_day",
"add_local_holidays",
"country",
"subdivision",
@@ -136,12 +138,22 @@
"fieldtype": "Button",
"label": "Add to Holidays",
"options": "get_local_holidays"
},
{
"fieldname": "column_break_euok",
"fieldtype": "Column Break"
},
{
"default": "0",
"fieldname": "is_half_day",
"fieldtype": "Check",
"label": "Is Half Day"
}
],
"icon": "fa fa-calendar",
"idx": 1,
"links": [],
"modified": "2024-03-27 13:09:49.920245",
"modified": "2025-08-28 15:17:05.313383",
"modified_by": "Administrator",
"module": "Setup",
"name": "Holiday List",
@@ -160,7 +172,8 @@
"write": 1
}
],
"row_format": "Dynamic",
"sort_field": "creation",
"sort_order": "DESC",
"states": []
}
}

View File

@@ -31,6 +31,7 @@ class HolidayList(Document):
from_date: DF.Date
holiday_list_name: DF.Data
holidays: DF.Table[Holiday]
is_half_day: DF.Check
subdivision: DF.Autocomplete | None
to_date: DF.Date
total_holidays: DF.Int
@@ -56,7 +57,15 @@ class HolidayList(Document):
if d in existing_holidays:
continue
self.append("holidays", {"description": _(self.weekly_off), "holiday_date": d, "weekly_off": 1})
self.append(
"holidays",
{
"description": _(self.weekly_off),
"holiday_date": d,
"weekly_off": 1,
"is_half_day": self.is_half_day,
},
)
@frappe.whitelist()
def get_supported_countries(self):
@@ -194,7 +203,25 @@ def is_holiday(holiday_list, date=None):
if date is None:
date = today()
if holiday_list:
return bool(frappe.db.exists("Holiday", {"parent": holiday_list, "holiday_date": date}, cache=True))
return bool(
frappe.db.exists(
"Holiday", {"parent": holiday_list, "holiday_date": date, "is_half_day": 0}, cache=True
)
)
else:
return False
def is_half_holiday(holiday_list, date=None):
"""Returns true if the given date is a half holiday in the given holiday list"""
if date is None:
date = today()
if holiday_list:
return bool(
frappe.db.exists(
"Holiday", {"parent": holiday_list, "holiday_date": date, "is_half_day": 1}, cache=True
)
)
else:
return False

View File

@@ -1,6 +1,5 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
import unittest
from contextlib import contextmanager
from datetime import date, timedelta

View File

@@ -136,7 +136,7 @@
"is_tree": 1,
"links": [],
"max_attachments": 3,
"modified": "2025-01-22 10:46:09.450137",
"modified": "2025-12-02 13:58:30.018021",
"modified_by": "Administrator",
"module": "Setup",
"name": "Item Group",
@@ -203,10 +203,11 @@
"share": 1
}
],
"row_format": "Dynamic",
"search_fields": "parent_item_group",
"show_name_in_global_search": 1,
"sort_field": "creation",
"sort_order": "DESC",
"states": [],
"translated_doctype": 1
}
}

View File

@@ -1,7 +1,6 @@
# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
import copy
import frappe
from frappe import _

View File

@@ -1,6 +1,5 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
import unittest
import frappe
from frappe.tests import IntegrationTestCase

View File

@@ -1,6 +1,5 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
import unittest
from frappe.tests import IntegrationTestCase

View File

@@ -1,4 +1,3 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
import frappe

View File

@@ -1,4 +1,3 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
import frappe

View File

@@ -42,6 +42,7 @@
{
"bold": 1,
"default": "0",
"description": "Only leaf nodes are allowed in transaction",
"fieldname": "is_group",
"fieldtype": "Check",
"in_list_view": 1,
@@ -108,7 +109,7 @@
"idx": 1,
"is_tree": 1,
"links": [],
"modified": "2025-01-22 10:49:27.066443",
"modified": "2025-12-02 13:57:57.814686",
"modified_by": "Administrator",
"module": "Setup",
"name": "Supplier Group",
@@ -168,9 +169,10 @@
"share": 1
}
],
"row_format": "Dynamic",
"show_name_in_global_search": 1,
"sort_field": "creation",
"sort_order": "ASC",
"states": [],
"translated_doctype": 1
}
}

View File

@@ -1,4 +1,3 @@
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
import frappe

View File

@@ -1,4 +1,3 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
import frappe

View File

@@ -46,6 +46,7 @@
{
"bold": 1,
"default": "0",
"description": "Only leaf nodes are allowed in transaction",
"fieldname": "is_group",
"fieldtype": "Check",
"in_list_view": 1,
@@ -123,7 +124,7 @@
"idx": 1,
"is_tree": 1,
"links": [],
"modified": "2024-08-16 19:21:19.161490",
"modified": "2025-12-02 13:58:55.190485",
"modified_by": "Administrator",
"module": "Setup",
"name": "Territory",
@@ -184,10 +185,11 @@
"share": 1
}
],
"row_format": "Dynamic",
"search_fields": "parent_territory,territory_manager",
"show_name_in_global_search": 1,
"sort_field": "creation",
"sort_order": "DESC",
"states": [],
"translated_doctype": 1
}
}

View File

@@ -1,4 +1,3 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
import frappe

View File

@@ -66,6 +66,9 @@ class TransactionDeletionRecord(Document):
}
)
def on_discard(self):
self.db_set("status", "Cancelled")
def validate(self):
frappe.only_for("System Manager")
self.validate_doctypes_to_be_ignored()
@@ -348,8 +351,9 @@ class TransactionDeletionRecord(Document):
self.db_set("error_log", None)
def get_doctypes_to_be_ignored_list(self):
singles = frappe.get_all("DocType", filters={"issingle": 1}, pluck="name")
doctypes_to_be_ignored_list = singles
doctypes_to_be_ignored_list = frappe.get_all(
"DocType", or_filters=[["issingle", "=", 1], ["is_virtual", "=", 1]], pluck="name"
)
for doctype in self.doctypes_to_be_ignored:
doctypes_to_be_ignored_list.append(doctype.doctype_name)
@@ -475,6 +479,7 @@ def get_doctypes_to_be_ignored():
"Item Default",
"Customer",
"Supplier",
"Department",
]
doctypes_to_be_ignored.extend(frappe.get_hooks("company_data_to_be_ignored") or [])

View File

@@ -1,4 +1,3 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
import frappe

View File

@@ -1,7 +1,2 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
//--------- ONLOAD -------------
cur_frm.cscript.onload = function (doc, cdt, cdn) {};
cur_frm.cscript.refresh = function (doc, cdt, cdn) {};

View File

@@ -1,6 +1,5 @@
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
import unittest
from frappe.tests import IntegrationTestCase

View File

@@ -1,6 +1,5 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
import unittest
import frappe
from frappe.tests import IntegrationTestCase

View File

@@ -5,12 +5,11 @@
import os
import frappe
from frappe import _
from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
from frappe.desk.page.setup_wizard.setup_wizard import add_all_roles_to
from frappe.utils import cint
from erpnext.setup.doctype.incoterm.incoterm import create_incoterms
from erpnext.setup.utils import identity as _
from .default_success_action import get_default_success_action
@@ -80,7 +79,7 @@ def setup_currency_exchange():
ces.set("result_key", [])
ces.set("req_params", [])
ces.api_endpoint = "https://api.frankfurter.app/{transaction_date}"
ces.api_endpoint = "https://api.frankfurter.dev/v1/{transaction_date}"
ces.append("result_key", {"key": "rates"})
ces.append("result_key", {"key": "{to_currency}"})
ces.append("req_params", {"key": "base", "value": "{from_currency}"})
@@ -184,33 +183,27 @@ def add_company_to_session_defaults():
def add_standard_navbar_items():
navbar_settings = frappe.get_single("Navbar Settings")
# Translatable strings for below navbar items
__ = _("Documentation")
__ = _("User Forum")
__ = _("Report an Issue")
erpnext_navbar_items = [
{
"item_label": "Documentation",
"item_label": _("Documentation"),
"item_type": "Route",
"route": "https://docs.erpnext.com/",
"is_standard": 1,
},
{
"item_label": "User Forum",
"item_label": _("User Forum"),
"item_type": "Route",
"route": "https://discuss.frappe.io",
"is_standard": 1,
},
{
"item_label": "Frappe School",
"item_label": _("Frappe School"),
"item_type": "Route",
"route": "https://frappe.io/school?utm_source=in_app",
"is_standard": 1,
},
{
"item_label": "Report an Issue",
"item_label": _("Report an Issue"),
"item_type": "Route",
"route": "https://github.com/frappe/erpnext/issues",
"is_standard": 1,
@@ -289,8 +282,20 @@ def update_pegged_currencies():
{"source_currency": "SAR", "pegged_against": "USD", "pegged_exchange_rate": 3.75},
]
# Add items on pegged_currency_item if source_currency and pegged_against currency doc exist.
currencies_exist = frappe.db.get_list(
"Currency", {"name": ["in", ["AED", "BHD", "JOD", "OMR", "QAR", "SAR", "USD"]]}, pluck="name"
)
if "USD" not in currencies_exist:
return
for currency in currencies_to_add:
if currency["source_currency"] not in existing_sources:
if (
currency["source_currency"] in currencies_exist
and currency["source_currency"] not in existing_sources
):
doc.append("pegged_currency_item", currency)
doc.save()
@@ -319,26 +324,26 @@ def create_letter_head():
DEFAULT_ROLE_PROFILES = {
"Inventory": [
_("Inventory"): [
"Stock User",
"Stock Manager",
"Item Manager",
],
"Manufacturing": [
_("Manufacturing"): [
"Stock User",
"Manufacturing User",
"Manufacturing Manager",
],
"Accounts": [
_("Accounts"): [
"Accounts User",
"Accounts Manager",
],
"Sales": [
_("Sales"): [
"Sales User",
"Stock User",
"Sales Manager",
],
"Purchase": [
_("Purchase"): [
"Item Manager",
"Stock User",
"Purchase User",

View File

@@ -15,14 +15,7 @@ from frappe.utils import cstr, getdate
from erpnext.accounts.doctype.account.account import RootNotEditable
from erpnext.regional.address_template.setup import set_up_address_templates
def _(x, *args, **kwargs):
"""Redefine the translation function to return the string as is.
We want to create english records but still mark the strings as translatable.
The respective DocTypes have 'Translate Link Fields' enabled."""
return x
from erpnext.setup.utils import identity as _
def read_lines(filename: str) -> list[str]:
@@ -579,7 +572,7 @@ def create_bank_account(args, demo=False):
return doc
except RootNotEditable:
frappe.throw(_("Bank account cannot be named as {0}").format(args.get("bank_account")))
frappe.throw(frappe._("Bank account cannot be named as {0}").format(args.get("bank_account")))
except frappe.DuplicateEntryError:
# bank account same as a CoA entry
pass

View File

@@ -4,7 +4,7 @@
import frappe
from frappe import _
from frappe.utils import add_days, flt, get_datetime_str, nowdate
from frappe.utils.data import getdate, now_datetime
from frappe.utils.data import now_datetime
from frappe.utils.nestedset import get_root_of
from erpnext import get_default_company
@@ -232,3 +232,15 @@ def welcome_email():
site_name = get_default_company() or "ERPNext"
title = _("Welcome to {0}").format(site_name)
return title
def identity(x, *args, **kwargs):
"""Used for redefining the translation function to return the string as is.
We want to create english records but still mark the strings as translatable.
E.g. when the respective DocTypes have 'Translate Link Fields' enabled or
we're creating custom fields.
Use like this: `from erpnext.setup.utils import identity as _`
"""
return x

View File

@@ -0,0 +1,133 @@
{
"app": "erpnext",
"charts": [],
"content": "[{\"id\":\"NO5yYHJopc\",\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Your Shortcuts\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t</b></span>\",\"col\":12}},{\"id\":\"CDxIM-WuZ9\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"System Settings\",\"col\":3}},{\"id\":\"-Uh7DKJNJX\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Accounts Settings\",\"col\":3}},{\"id\":\"K9ST9xcDXh\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Stock Settings\",\"col\":3}},{\"id\":\"27IdVHVQMb\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Selling Settings\",\"col\":3}},{\"id\":\"Rwp5zff88b\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Buying Settings\",\"col\":3}},{\"id\":\"hkfnQ2sevf\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Global Defaults\",\"col\":3}},{\"id\":\"jjxI_PDawD\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Print Settings\",\"col\":3}}]",
"creation": "2022-01-27 13:14:47.349433",
"custom_blocks": [],
"docstatus": 0,
"doctype": "Workspace",
"for_user": "",
"hide_custom": 0,
"icon": "setting",
"idx": 0,
"is_hidden": 0,
"label": "ERPNext Settings",
"links": [
{
"dependencies": "",
"hidden": 0,
"is_query_report": 0,
"label": "Import Data",
"link_count": 0,
"link_to": "Data Import",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
},
{
"dependencies": "",
"hidden": 0,
"is_query_report": 0,
"label": "Export Data",
"link_count": 0,
"link_to": "Data Export",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
},
{
"dependencies": "",
"hidden": 0,
"is_query_report": 0,
"label": "Bulk Update",
"link_count": 0,
"link_to": "Bulk Update",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
},
{
"dependencies": "",
"hidden": 0,
"is_query_report": 0,
"label": "Download Backups",
"link_count": 0,
"link_to": "backups",
"link_type": "Page",
"onboard": 0,
"type": "Link"
},
{
"dependencies": "",
"hidden": 0,
"is_query_report": 0,
"label": "Deleted Documents",
"link_count": 0,
"link_to": "Deleted Document",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
}
],
"modified": "2026-01-09 13:05:08.007297",
"modified_by": "Administrator",
"module": "Setup",
"name": "ERPNext Settings",
"number_cards": [],
"owner": "Administrator",
"parent_page": "",
"public": 1,
"quick_lists": [],
"restrict_to_domain": "",
"roles": [],
"sequence_id": 19.0,
"shortcuts": [
{
"color": "Grey",
"doc_view": "List",
"label": "Print Settings",
"link_to": "Print Settings",
"type": "DocType"
},
{
"color": "Grey",
"doc_view": "List",
"label": "System Settings",
"link_to": "System Settings",
"type": "DocType"
},
{
"icon": "accounting",
"label": "Accounts Settings",
"link_to": "Accounts Settings",
"type": "DocType"
},
{
"color": "Grey",
"doc_view": "List",
"label": "Global Defaults",
"link_to": "Global Defaults",
"type": "DocType"
},
{
"icon": "stock",
"label": "Stock Settings",
"link_to": "Stock Settings",
"type": "DocType"
},
{
"icon": "sell",
"label": "Selling Settings",
"link_to": "Selling Settings",
"type": "DocType"
},
{
"icon": "buying",
"label": "Buying Settings",
"link_to": "Buying Settings",
"type": "DocType"
}
],
"title": "ERPNext Settings",
"type": "Workspace"
}

View File

@@ -1,489 +0,0 @@
{
"charts": [],
"content": "[{\"id\":\"NO5yYHJopc\",\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Your Shortcuts\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t</b></span>\",\"col\":12}},{\"id\":\"CDxIM-WuZ9\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"System Settings\",\"col\":3}},{\"id\":\"-Uh7DKJNJX\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Accounts Settings\",\"col\":3}},{\"id\":\"K9ST9xcDXh\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Stock Settings\",\"col\":3}},{\"id\":\"27IdVHVQMb\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Selling Settings\",\"col\":3}},{\"id\":\"Rwp5zff88b\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Buying Settings\",\"col\":3}},{\"id\":\"hkfnQ2sevf\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Global Defaults\",\"col\":3}},{\"id\":\"jjxI_PDawD\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Print Settings\",\"col\":3}},{\"id\":\"R3CoYYFXye\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"yynbm1J_VO\",\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Settings</b></span>\",\"col\":12}},{\"id\":\"KDCv2MvSg3\",\"type\":\"card\",\"data\":{\"card_name\":\"Module Settings\",\"col\":4}},{\"id\":\"Q0_bqT7cxQ\",\"type\":\"card\",\"data\":{\"card_name\":\"Email / Notifications\",\"col\":4}},{\"id\":\"UnqK5haBnh\",\"type\":\"card\",\"data\":{\"card_name\":\"Website\",\"col\":4}},{\"id\":\"kp7u1H5hCd\",\"type\":\"card\",\"data\":{\"card_name\":\"Core\",\"col\":4}},{\"id\":\"Ufc3jycgy9\",\"type\":\"card\",\"data\":{\"card_name\":\"Printing\",\"col\":4}},{\"id\":\"89bSNzv3Yh\",\"type\":\"card\",\"data\":{\"card_name\":\"Workflow\",\"col\":4}}]",
"creation": "2022-01-27 13:14:47.349433",
"custom_blocks": [],
"docstatus": 0,
"doctype": "Workspace",
"for_user": "",
"hide_custom": 0,
"icon": "setting",
"idx": 0,
"is_hidden": 0,
"label": "Settings",
"links": [
{
"dependencies": "",
"hidden": 0,
"is_query_report": 0,
"label": "Import Data",
"link_count": 0,
"link_to": "Data Import",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
},
{
"dependencies": "",
"hidden": 0,
"is_query_report": 0,
"label": "Export Data",
"link_count": 0,
"link_to": "Data Export",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
},
{
"dependencies": "",
"hidden": 0,
"is_query_report": 0,
"label": "Bulk Update",
"link_count": 0,
"link_to": "Bulk Update",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
},
{
"dependencies": "",
"hidden": 0,
"is_query_report": 0,
"label": "Download Backups",
"link_count": 0,
"link_to": "backups",
"link_type": "Page",
"onboard": 0,
"type": "Link"
},
{
"dependencies": "",
"hidden": 0,
"is_query_report": 0,
"label": "Deleted Documents",
"link_count": 0,
"link_to": "Deleted Document",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
},
{
"hidden": 0,
"is_query_report": 0,
"label": "Email / Notifications",
"link_count": 0,
"onboard": 0,
"type": "Card Break"
},
{
"dependencies": "",
"hidden": 0,
"is_query_report": 0,
"label": "Email Account",
"link_count": 0,
"link_to": "Email Account",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
},
{
"dependencies": "",
"hidden": 0,
"is_query_report": 0,
"label": "Email Domain",
"link_count": 0,
"link_to": "Email Domain",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
},
{
"dependencies": "",
"hidden": 0,
"is_query_report": 0,
"label": "Notification",
"link_count": 0,
"link_to": "Notification",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
},
{
"dependencies": "",
"hidden": 0,
"is_query_report": 0,
"label": "Email Template",
"link_count": 0,
"link_to": "Email Template",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
},
{
"dependencies": "",
"hidden": 0,
"is_query_report": 0,
"label": "Auto Email Report",
"link_count": 0,
"link_to": "Auto Email Report",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
},
{
"dependencies": "",
"hidden": 0,
"is_query_report": 0,
"label": "Notification Settings",
"link_count": 0,
"link_to": "Notification Settings",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
},
{
"hidden": 0,
"is_query_report": 0,
"label": "Website",
"link_count": 0,
"onboard": 0,
"type": "Card Break"
},
{
"dependencies": "",
"hidden": 0,
"is_query_report": 0,
"label": "Website Settings",
"link_count": 0,
"link_to": "Website Settings",
"link_type": "DocType",
"onboard": 1,
"type": "Link"
},
{
"dependencies": "",
"hidden": 0,
"is_query_report": 0,
"label": "Website Theme",
"link_count": 0,
"link_to": "Website Theme",
"link_type": "DocType",
"onboard": 1,
"type": "Link"
},
{
"dependencies": "",
"hidden": 0,
"is_query_report": 0,
"label": "Website Script",
"link_count": 0,
"link_to": "Website Script",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
},
{
"dependencies": "",
"hidden": 0,
"is_query_report": 0,
"label": "About Us Settings",
"link_count": 0,
"link_to": "About Us Settings",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
},
{
"dependencies": "",
"hidden": 0,
"is_query_report": 0,
"label": "Contact Us Settings",
"link_count": 0,
"link_to": "Contact Us Settings",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
},
{
"hidden": 0,
"is_query_report": 0,
"label": "Printing",
"link_count": 0,
"onboard": 0,
"type": "Card Break"
},
{
"dependencies": "",
"hidden": 0,
"is_query_report": 0,
"label": "Print Format Builder",
"link_count": 0,
"link_to": "print-format-builder",
"link_type": "Page",
"onboard": 0,
"type": "Link"
},
{
"dependencies": "",
"hidden": 0,
"is_query_report": 0,
"label": "Print Settings",
"link_count": 0,
"link_to": "Print Settings",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
},
{
"dependencies": "",
"hidden": 0,
"is_query_report": 0,
"label": "Print Format",
"link_count": 0,
"link_to": "Print Format",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
},
{
"dependencies": "",
"hidden": 0,
"is_query_report": 0,
"label": "Print Style",
"link_count": 0,
"link_to": "Print Style",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
},
{
"hidden": 0,
"is_query_report": 0,
"label": "Workflow",
"link_count": 0,
"onboard": 0,
"type": "Card Break"
},
{
"dependencies": "",
"hidden": 0,
"is_query_report": 0,
"label": "Workflow",
"link_count": 0,
"link_to": "Workflow",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
},
{
"dependencies": "",
"hidden": 0,
"is_query_report": 0,
"label": "Workflow State",
"link_count": 0,
"link_to": "Workflow State",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
},
{
"dependencies": "",
"hidden": 0,
"is_query_report": 0,
"label": "Workflow Action",
"link_count": 0,
"link_to": "Workflow Action",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
},
{
"hidden": 0,
"is_query_report": 0,
"label": "Core",
"link_count": 3,
"onboard": 0,
"type": "Card Break"
},
{
"dependencies": "",
"hidden": 0,
"is_query_report": 0,
"label": "System Settings",
"link_count": 0,
"link_to": "System Settings",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
},
{
"dependencies": "",
"hidden": 0,
"is_query_report": 0,
"label": "Domain Settings",
"link_count": 0,
"link_to": "Domain Settings",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
},
{
"hidden": 0,
"is_query_report": 0,
"label": "Global Defaults",
"link_count": 0,
"link_to": "Global Defaults",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
},
{
"hidden": 0,
"is_query_report": 0,
"label": "Module Settings",
"link_count": 8,
"onboard": 0,
"type": "Card Break"
},
{
"hidden": 0,
"is_query_report": 0,
"label": "Accounts Settings",
"link_count": 0,
"link_to": "Accounts Settings",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
},
{
"hidden": 0,
"is_query_report": 0,
"label": "Stock Settings",
"link_count": 0,
"link_to": "Stock Settings",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
},
{
"hidden": 0,
"is_query_report": 0,
"label": "Selling Settings",
"link_count": 0,
"link_to": "Selling Settings",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
},
{
"hidden": 0,
"is_query_report": 0,
"label": "Buying Settings",
"link_count": 0,
"link_to": "Buying Settings",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
},
{
"hidden": 0,
"is_query_report": 0,
"label": "Manufacturing Settings",
"link_count": 0,
"link_to": "Manufacturing Settings",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
},
{
"hidden": 0,
"is_query_report": 0,
"label": "CRM Settings",
"link_count": 0,
"link_to": "CRM Settings",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
},
{
"hidden": 0,
"is_query_report": 0,
"label": "Projects Settings",
"link_count": 0,
"link_to": "Projects Settings",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
},
{
"hidden": 0,
"is_query_report": 0,
"label": "Support Settings",
"link_count": 0,
"link_to": "Support Settings",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
}
],
"modified": "2024-01-02 15:17:30.421357",
"modified_by": "Administrator",
"module": "Setup",
"name": "Settings",
"number_cards": [],
"owner": "Administrator",
"parent_page": "",
"public": 1,
"quick_lists": [],
"restrict_to_domain": "",
"roles": [],
"sequence_id": 19.0,
"shortcuts": [
{
"color": "Grey",
"doc_view": "List",
"label": "Print Settings",
"link_to": "Print Settings",
"type": "DocType"
},
{
"color": "Grey",
"doc_view": "List",
"label": "System Settings",
"link_to": "System Settings",
"type": "DocType"
},
{
"icon": "accounting",
"label": "Accounts Settings",
"link_to": "Accounts Settings",
"type": "DocType"
},
{
"color": "Grey",
"doc_view": "List",
"label": "Global Defaults",
"link_to": "Global Defaults",
"type": "DocType"
},
{
"icon": "stock",
"label": "Stock Settings",
"link_to": "Stock Settings",
"type": "DocType"
},
{
"icon": "sell",
"label": "Selling Settings",
"link_to": "Selling Settings",
"type": "DocType"
},
{
"icon": "buying",
"label": "Buying Settings",
"link_to": "Buying Settings",
"type": "DocType"
}
],
"title": "Settings"
}