Merge branch 'frappe:develop' into tabs_on_grid_row_form
This commit is contained in:
commit
9c06b6e089
21 changed files with 908 additions and 678 deletions
|
|
@ -3,7 +3,7 @@ const jump_to_field = (field_label) => {
|
|||
.type("{esc}") // lose focus if any
|
||||
.type("{ctrl+j}") // jump to field
|
||||
.type(field_label)
|
||||
.wait(500)
|
||||
.wait(1000)
|
||||
.type("{enter}")
|
||||
.wait(200)
|
||||
.findByRole("button", { name: "Go" })
|
||||
|
|
|
|||
|
|
@ -528,18 +528,27 @@ def get_sentry_dsn():
|
|||
|
||||
|
||||
def get_sidebar_items():
|
||||
from frappe.desk.doctype.workspace_sidebar.workspace_sidebar import auto_generate_sidebar_from_module
|
||||
|
||||
sidebars = frappe.get_all(
|
||||
"Workspace Sidebar", fields=["name", "header_icon"], filters={"name": ["not like", "%My Workspaces%"]}
|
||||
)
|
||||
module_sidebars = auto_generate_sidebar_from_module()
|
||||
sidebars.extend(module_sidebars)
|
||||
add_user_specific_sidebar(sidebars)
|
||||
sidebar_items = {}
|
||||
|
||||
for s in sidebars:
|
||||
w = frappe.get_doc("Workspace Sidebar", s["name"])
|
||||
sidebar_items[s["name"].lower()] = {
|
||||
"label": s["name"],
|
||||
sidebar_title = s.get("name")
|
||||
if sidebar_title:
|
||||
w = frappe.get_doc("Workspace Sidebar", sidebar_title)
|
||||
else:
|
||||
sidebar_title = s.title
|
||||
w = s
|
||||
sidebar_items[sidebar_title.lower()] = {
|
||||
"label": sidebar_title,
|
||||
"items": [],
|
||||
"header_icon": s["header_icon"],
|
||||
"header_icon": s.get("header_icon"),
|
||||
"module": w.module,
|
||||
"app": w.app,
|
||||
}
|
||||
|
|
@ -568,13 +577,12 @@ def get_sidebar_items():
|
|||
"report_type": report_type,
|
||||
"ref_doctype": ref_doctype,
|
||||
}
|
||||
|
||||
if (
|
||||
"My Workspaces" in s["name"]
|
||||
"My Workspaces" in sidebar_title
|
||||
or si.type == "Section Break"
|
||||
or w.is_item_allowed(si.link_to, si.link_type)
|
||||
):
|
||||
sidebar_items[s["name"].lower()]["items"].append(workspace_sidebar)
|
||||
sidebar_items[sidebar_title.lower()]["items"].append(workspace_sidebar)
|
||||
|
||||
old_name = f"my workspaces-{frappe.session.user.lower()}"
|
||||
if old_name in sidebar_items.keys():
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ class TestServerScript(IntegrationTestCase):
|
|||
self.assertEqual(frappe.get_doc("Server Script", "test_return_value").execute_method(), "hello")
|
||||
|
||||
def test_permission_query(self):
|
||||
sql = frappe.db.get_list("ToDo", run=False)
|
||||
sql = frappe.db.get_list("ToDo", run=False).get_sql()
|
||||
self.assertTrue("where (1 = 1)" in sql.lower())
|
||||
self.assertTrue(isinstance(frappe.db.get_list("ToDo"), list))
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ frappe.pages["dashboard-view"].on_page_load = function (wrapper) {
|
|||
class Dashboard {
|
||||
constructor(wrapper) {
|
||||
this.wrapper = $(wrapper);
|
||||
$(`<div class="dashboard" style="overflow: visible; margin: var(--margin-sm);">
|
||||
$(`<div class="dashboard" style="overflow: visible; margin: var(--margin-md);">
|
||||
<div class="dashboard-graph"></div>
|
||||
</div>`).appendTo(this.wrapper.find(".page-content").empty());
|
||||
this.container = this.wrapper.find(".dashboard-graph");
|
||||
|
|
|
|||
|
|
@ -1089,22 +1089,22 @@ class Database:
|
|||
|
||||
Query will be built as:
|
||||
```sql
|
||||
UPDATE `tabItem`
|
||||
UPDATE `tabTask`
|
||||
SET `status` = CASE
|
||||
WHEN `name` = 'Item-1' THEN 'Close'
|
||||
WHEN `name` = 'Item-2' THEN 'Open'
|
||||
WHEN `name` = 'Item-3' THEN 'Close'
|
||||
WHEN `name` = 'Item-4' THEN 'Cancelled'
|
||||
WHEN `name` = 'TASK-0001' THEN 'Closed'
|
||||
WHEN `name` = 'TASK-0002' THEN 'Open'
|
||||
WHEN `name` = 'TASK-0003' THEN 'Closed'
|
||||
WHEN `name` = 'TASK-0004' THEN 'Cancelled'
|
||||
ELSE `status`
|
||||
end,
|
||||
END,
|
||||
`description` = CASE
|
||||
WHEN `name` = 'Item-1' THEN 'This is the first task'
|
||||
WHEN `name` = 'Item-2' THEN 'This is the second task'
|
||||
WHEN `name` = 'Item-3' THEN 'This is the third task'
|
||||
WHEN `name` = 'Item-4' THEN 'This is the fourth task'
|
||||
WHEN `name` = 'TASK-0001' THEN 'This is the first task'
|
||||
WHEN `name` = 'TASK-0002' THEN 'This is the second task'
|
||||
WHEN `name` = 'TASK-0003' THEN 'This is the third task'
|
||||
WHEN `name` = 'TASK-0004' THEN 'This is the fourth task'
|
||||
ELSE `description`
|
||||
end
|
||||
WHERE `name` IN ( 'Item-1', 'Item-2', 'Item-3', 'Item-4' )
|
||||
END
|
||||
WHERE `name` IN ('TASK-0001', 'TASK-0002', 'TASK-0003', 'TASK-0004');
|
||||
```
|
||||
"""
|
||||
if not doc_updates:
|
||||
|
|
|
|||
|
|
@ -79,6 +79,44 @@ def _apply_date_field_filter_conversion(value, operator: str, doctype: str, fiel
|
|||
return value
|
||||
|
||||
|
||||
def _apply_datetime_field_filter_conversion(between_values: tuple | list, doctype: str, field) -> tuple:
|
||||
"""Apply date to datetime conversion for Datetime fields with 'between' operator.
|
||||
|
||||
Args:
|
||||
between_values: Tuple/list of two values [from, to] for between filter
|
||||
doctype: DocType name
|
||||
field: Field name or pypika Field object
|
||||
|
||||
Returns:
|
||||
Tuple with dates expanded to datetime ranges for Datetime fields
|
||||
"""
|
||||
from frappe.model.db_query import _convert_type_for_between_filters
|
||||
|
||||
# Extract field name
|
||||
field_name = field
|
||||
if "." in str(field):
|
||||
field_name = field.split(".")[-1]
|
||||
|
||||
# Skip querying meta for core doctypes to avoid recursion
|
||||
if doctype in CORE_DOCTYPES:
|
||||
df = None
|
||||
else:
|
||||
meta = frappe.get_meta(doctype)
|
||||
df = meta.get_field(field_name) if meta else None
|
||||
|
||||
# Standard datetime fields or Datetime fieldtype
|
||||
if not (field_name in ("creation", "modified") or (df and df.fieldtype == "Datetime")):
|
||||
return between_values
|
||||
|
||||
from_val, to_val = between_values
|
||||
|
||||
# Convert to datetime using db_query helper (handles strings, dates, datetimes)
|
||||
from_val = _convert_type_for_between_filters(from_val, set_time=datetime.time())
|
||||
to_val = _convert_type_for_between_filters(to_val, set_time=datetime.time(23, 59, 59, 999999))
|
||||
|
||||
return (from_val, to_val)
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from frappe.query_builder import DocType
|
||||
|
||||
|
|
@ -487,12 +525,22 @@ class Engine:
|
|||
frappe.throw(_("Document cannot be used as a filter value"))
|
||||
_operator = operator
|
||||
|
||||
if _operator.lower() in ("timespan", "previous", "next"):
|
||||
from frappe.model.db_query import get_date_range
|
||||
|
||||
_value = get_date_range(_operator.lower(), _value)
|
||||
_operator = "between"
|
||||
|
||||
# For Date fields with datetime values, convert to date to match db_query behavior
|
||||
if isinstance(_value, datetime.datetime) or (
|
||||
isinstance(_value, list | tuple) and any(isinstance(v, datetime.datetime) for v in _value)
|
||||
):
|
||||
_value = _apply_date_field_filter_conversion(_value, _operator, doctype or self.doctype, field)
|
||||
|
||||
# For Datetime fields with date values and 'between' operator, convert to datetime range to match db_query
|
||||
if _operator.lower() == "between" and isinstance(_value, list | tuple) and len(_value) == 2:
|
||||
_value = _apply_datetime_field_filter_conversion(_value, doctype or self.doctype, field)
|
||||
|
||||
if not _value and isinstance(_value, list | tuple | set):
|
||||
_value = ("",)
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ from frappe.boot import get_allowed_pages, get_allowed_reports
|
|||
from frappe.model.document import Document
|
||||
from frappe.modules.export_file import strip_default_fields
|
||||
from frappe.modules.utils import create_directory_on_app_path
|
||||
from frappe.utils.caching import site_cache
|
||||
|
||||
|
||||
class WorkspaceSidebar(Document):
|
||||
|
|
@ -240,3 +241,134 @@ def add_to_my_workspace(workspace):
|
|||
|
||||
except Exception as e:
|
||||
frappe.log_error(title="Error in Adding Private Workspaces", message=e)
|
||||
|
||||
|
||||
@site_cache()
|
||||
def auto_generate_sidebar_from_module():
|
||||
"""Auto generate sidebar from module"""
|
||||
sidebars = []
|
||||
for module in frappe.get_all("Module Def", pluck="name"):
|
||||
if not (
|
||||
frappe.db.exists("Workspace Sidebar", {"module": module})
|
||||
or frappe.db.exists("Workspace Sidebar", {"name": module})
|
||||
):
|
||||
module_info = get_module_info(module)
|
||||
sidebar_items = create_sidebar_items(module_info)
|
||||
sidebar = frappe.new_doc("Workspace Sidebar")
|
||||
sidebar.title = module
|
||||
sidebar.items = sidebar_items
|
||||
sidebar.module = module
|
||||
sidebar.header_icon = "hammer"
|
||||
sidebar.app = frappe.local.module_app.get(frappe.scrub(module), None)
|
||||
sidebars.append(sidebar)
|
||||
return sidebars
|
||||
|
||||
|
||||
def get_module_info(module_name):
|
||||
entities = ["Workspace", "Dashboard", "DocType", "Report", "Page"]
|
||||
module_info = {}
|
||||
|
||||
for entity in entities:
|
||||
module_info[entity] = {}
|
||||
filters = [{"module": module_name}]
|
||||
pluck = "name"
|
||||
fieldnames = ["name"]
|
||||
if entity.lower() == "doctype":
|
||||
filters.append({"istable": 0})
|
||||
if entity.lower() == "page":
|
||||
fieldnames.append("title")
|
||||
pluck = None
|
||||
module_info[entity] = frappe.get_all(
|
||||
entity, filters=filters, fields=fieldnames, pluck=pluck, order_by="creation asc"
|
||||
)
|
||||
|
||||
# if module info has no workspaces, then move doctypes to the front
|
||||
if not module_info.get("Workspace"):
|
||||
module_info = {
|
||||
"DocType": module_info.get("DocType"),
|
||||
"Workspace": module_info.get("Workspace"),
|
||||
"Report": module_info.get("Report"),
|
||||
"Dashboard": module_info.get("Dashboard"),
|
||||
"Page": module_info.get("Page"),
|
||||
}
|
||||
top_doctypes = choose_top_doctypes(module_info.get("DocType"))
|
||||
if top_doctypes:
|
||||
module_info["DocType"] = choose_top_doctypes(module_info.get("DocType"))
|
||||
return module_info
|
||||
|
||||
|
||||
def choose_top_doctypes(doctype_names):
|
||||
doctype_limit = 3
|
||||
if len(doctype_names) > doctype_limit:
|
||||
try:
|
||||
doctype_count_map = {}
|
||||
for doctype in doctype_names:
|
||||
doctype_count_map[doctype] = frappe.db.count(doctype)
|
||||
top_doctypes = [
|
||||
name
|
||||
for name, count in sorted(doctype_count_map.items(), key=lambda x: x[1], reverse=True)[
|
||||
:doctype_limit
|
||||
]
|
||||
]
|
||||
return top_doctypes
|
||||
except frappe.db.ProgrammingError:
|
||||
# catches table not found errors
|
||||
return None
|
||||
|
||||
|
||||
def create_sidebar_items(module_info):
|
||||
sidebar_items = []
|
||||
idx = 1
|
||||
|
||||
section_entities = {"report": "Reports", "dashboard": "Dashboards", "page": "Pages"}
|
||||
|
||||
for entity, items in module_info.items():
|
||||
section_break_added = False
|
||||
entity_lower = entity.lower()
|
||||
|
||||
if entity_lower in section_entities:
|
||||
if entity_lower == "report":
|
||||
section_break = add_section_breaks("Reports", idx)
|
||||
elif entity_lower in ("dashboard", "page") and len(items) > 1:
|
||||
section_break = add_section_breaks(section_entities[entity_lower], idx)
|
||||
section_break_added = True
|
||||
sidebar_items.append(section_break)
|
||||
idx += 1
|
||||
|
||||
for item in items:
|
||||
item_info = {"label": item, "type": "Link", "link_type": entity, "link_to": item, "idx": idx}
|
||||
|
||||
if entity_lower == "report":
|
||||
item_info["child"] = 1
|
||||
item_info["icon"] = "table"
|
||||
|
||||
if entity_lower == "page":
|
||||
item_info["label"] = item.get("title")
|
||||
item_info["link_to"] = item.get("name")
|
||||
|
||||
if entity_lower == "workspace":
|
||||
item_info["icon"] = "home"
|
||||
item_info["icon"] = "wallpaper"
|
||||
|
||||
if entity_lower == "page":
|
||||
item_info["icon"] = "panel-top"
|
||||
|
||||
if entity_lower == "doctype" and "settings" in item.lower():
|
||||
item_info["icon"] = "settings"
|
||||
|
||||
if section_break_added:
|
||||
item_info["child"] = 1
|
||||
|
||||
sidebar_item = frappe.new_doc("Workspace Sidebar Item")
|
||||
sidebar_item.update(item_info)
|
||||
sidebar_items.append(sidebar_item)
|
||||
|
||||
idx += 1
|
||||
|
||||
return sidebar_items
|
||||
|
||||
|
||||
def add_section_breaks(label, idx):
|
||||
section_break = frappe.new_doc("Workspace Sidebar Item")
|
||||
section_break.update({"label": label, "type": "Section Break", "idx": idx})
|
||||
return section_break
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ msgstr ""
|
|||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: developers@frappe.io\n"
|
||||
"POT-Creation-Date: 2025-11-30 09:34+0000\n"
|
||||
"PO-Revision-Date: 2025-12-02 15:00\n"
|
||||
"PO-Revision-Date: 2025-12-06 16:40\n"
|
||||
"Last-Translator: developers@frappe.io\n"
|
||||
"Language-Team: Persian\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
@ -1660,7 +1660,7 @@ msgstr "به API Indexing Access اجازه دهید"
|
|||
#: frappe/core/doctype/doctype/doctype.json
|
||||
#: frappe/custom/doctype/customize_form/customize_form.json
|
||||
msgid "Allow Auto Repeat"
|
||||
msgstr "تکرار خودکار مجاز است"
|
||||
msgstr "اجازه تکرار خودکار"
|
||||
|
||||
#. Label of the allow_bulk_edit (Check) field in DocType 'DocField'
|
||||
#. Label of the allow_bulk_edit (Check) field in DocType 'Customize Form Field'
|
||||
|
|
@ -1743,7 +1743,7 @@ msgstr "اجازه دادن به پیوندهای نمای وب قدیمی (نا
|
|||
#. Settings'
|
||||
#: frappe/printing/doctype/print_settings/print_settings.json
|
||||
msgid "Allow Print for Cancelled"
|
||||
msgstr "چاپ برای لغو مجاز است"
|
||||
msgstr "اجازه چاپ برای لغو شده"
|
||||
|
||||
#. Label of the allow_print_for_draft (Check) field in DocType 'Print Settings'
|
||||
#: frappe/automation/doctype/auto_repeat/auto_repeat.py:438
|
||||
|
|
@ -6756,7 +6756,7 @@ msgstr "وضعیت ها و قوانین گردش کار را برای یک سن
|
|||
#. Option for the 'Delivery Status' (Select) field in DocType 'Communication'
|
||||
#: frappe/core/doctype/communication/communication.json
|
||||
msgid "Delayed"
|
||||
msgstr ""
|
||||
msgstr "با تاخیر"
|
||||
|
||||
#. Label of the delete (Check) field in DocType 'Custom DocPerm'
|
||||
#. Label of the delete (Check) field in DocType 'DocPerm'
|
||||
|
|
@ -6949,7 +6949,7 @@ msgstr "جداکننده باید یک کاراکتر واحد باشد"
|
|||
#. Label of the delivery_status (Select) field in DocType 'Communication'
|
||||
#: frappe/core/doctype/communication/communication.json
|
||||
msgid "Delivery Status"
|
||||
msgstr ""
|
||||
msgstr "وضعیت تحویل"
|
||||
|
||||
#. Option for the 'Sign ups' (Select) field in DocType 'Social Login Key'
|
||||
#: frappe/integrations/doctype/social_login_key/social_login_key.json
|
||||
|
|
@ -6960,7 +6960,7 @@ msgstr "انکار"
|
|||
#. Label of the department (Data) field in DocType 'Contact'
|
||||
#: frappe/contacts/doctype/contact/contact.json
|
||||
msgid "Department"
|
||||
msgstr ""
|
||||
msgstr "دپارتمان"
|
||||
|
||||
#. Label of the dependencies (Data) field in DocType 'Workspace Link'
|
||||
#: frappe/desk/doctype/workspace_link/workspace_link.json
|
||||
|
|
@ -15693,7 +15693,7 @@ msgstr "استفاده از حافظه"
|
|||
|
||||
#: frappe/core/report/prepared_report_analytics/prepared_report_analytics.py:63
|
||||
msgid "Memory Usage in MB"
|
||||
msgstr ""
|
||||
msgstr "میزان استفاده از حافظه برحسب مگابایت"
|
||||
|
||||
#. Option for the 'Type' (Select) field in DocType 'Notification Log'
|
||||
#: frappe/desk/doctype/notification_log/notification_log.json
|
||||
|
|
@ -18464,7 +18464,7 @@ msgstr "تولید PDF در حال انجام است"
|
|||
#. Label of the pdf_generator (Select) field in DocType 'Print Format'
|
||||
#: frappe/printing/doctype/print_format/print_format.json
|
||||
msgid "PDF Generator"
|
||||
msgstr ""
|
||||
msgstr "سازنده PDF"
|
||||
|
||||
#. Label of the pdf_page_height (Float) field in DocType 'Print Settings'
|
||||
#: frappe/printing/doctype/print_settings/print_settings.json
|
||||
|
|
@ -19087,7 +19087,7 @@ msgstr "نوع مجوز"
|
|||
|
||||
#: frappe/core/doctype/permission_type/permission_type.py:40
|
||||
msgid "Permission Type '{0}' is reserved. Please choose another name."
|
||||
msgstr ""
|
||||
msgstr "نوع مجوز '{0}' رزرو شده است. لطفاً نام دیگری انتخاب کنید."
|
||||
|
||||
#. Label of the section_break_4 (Section Break) field in DocType 'Custom
|
||||
#. DocPerm'
|
||||
|
|
@ -19325,7 +19325,7 @@ msgstr ""
|
|||
|
||||
#: frappe/core/doctype/data_import/data_import.js:164
|
||||
msgid "Please click on 'Export Errored Rows', fix the errors and import again."
|
||||
msgstr ""
|
||||
msgstr "لطفاً روی «برونبُرد ردیفهای دارای خطا» کلیک کنید، خطاها را برطرف کرده و دوباره درونبُرد کنید."
|
||||
|
||||
#: frappe/twofactor.py:286
|
||||
msgid "Please click on the following link and follow the instructions on the page. {0}"
|
||||
|
|
@ -19648,7 +19648,7 @@ msgstr "لطفاً از یک فیلتر جستجوی معتبر LDAP استفا
|
|||
|
||||
#: frappe/templates/emails/file_backup_notification.html:4
|
||||
msgid "Please use following links to download file backup."
|
||||
msgstr ""
|
||||
msgstr "لطفا برای دانلود فایل پشتیبان از لینکهای زیر استفاده کنید."
|
||||
|
||||
#: frappe/utils/password.py:217
|
||||
msgid "Please visit https://frappecloud.com/docs/sites/migrate-an-existing-site#encryption-key for more information."
|
||||
|
|
@ -24281,7 +24281,7 @@ msgstr "نمایش ردیابی"
|
|||
#. Chart'
|
||||
#: frappe/desk/doctype/dashboard_chart/dashboard_chart.json
|
||||
msgid "Show Values over Chart"
|
||||
msgstr ""
|
||||
msgstr "نمایش مقادیر روی نمودار"
|
||||
|
||||
#: frappe/public/js/frappe/data_import/import_preview.js:204
|
||||
msgid "Show Warnings"
|
||||
|
|
@ -24524,7 +24524,7 @@ msgstr "حجم (مگابایت)"
|
|||
|
||||
#: frappe/public/js/frappe/file_uploader/FileUploader.vue:629
|
||||
msgid "Size exceeds the maximum allowed file size."
|
||||
msgstr ""
|
||||
msgstr "حجم فایل از حداکثر حجم مجاز بیشتر است."
|
||||
|
||||
#: frappe/public/js/frappe/widgets/onboarding_widget.js:82
|
||||
#: frappe/public/js/onboarding_tours/onboarding_tours.js:18
|
||||
|
|
@ -25348,7 +25348,7 @@ msgstr "پاسخ دیگری را ثبت کنید"
|
|||
#. Label of the button_label (Data) field in DocType 'Web Form'
|
||||
#: frappe/website/doctype/web_form/web_form.json
|
||||
msgid "Submit button label"
|
||||
msgstr ""
|
||||
msgstr "برچسب دکمه ارسال"
|
||||
|
||||
#. Label of the submit_on_creation (Check) field in DocType 'Auto Repeat'
|
||||
#: frappe/automation/doctype/auto_repeat/auto_repeat.json
|
||||
|
|
@ -26610,7 +26610,7 @@ msgstr "این سند پس از ارسال ایمیل اصلاح شده است."
|
|||
|
||||
#: frappe/public/js/frappe/form/form.js:1317
|
||||
msgid "This document has unsaved changes which might not appear in final PDF. <br> Consider saving the document before printing."
|
||||
msgstr ""
|
||||
msgstr "این سند دارای تغییرات ذخیرهنشده است که ممکن است در فایل PDF نهایی نمایش داده نشوند. <br> قبل از چاپ، سند را ذخیره کنید."
|
||||
|
||||
#: frappe/public/js/frappe/form/form.js:1105
|
||||
msgid "This document is already amended, you cannot ammend it again"
|
||||
|
|
@ -26649,7 +26649,7 @@ msgstr "این فایل به یک سند محافظت شده پیوست شده
|
|||
|
||||
#: frappe/public/js/frappe/file_uploader/FilePreview.vue:76
|
||||
msgid "This file is public and can be accessed by anyone, even without logging in. Mark it private to limit access."
|
||||
msgstr ""
|
||||
msgstr "این فایل عمومی است و هر کسی میتواند به آن دسترسی داشته باشد، حتی بدون ورود به سیستم. برای محدود کردن دسترسی، آن را خصوصی علامتگذاری کنید."
|
||||
|
||||
#: frappe/core/doctype/file/file.js:20
|
||||
msgid "This file is public. It can be accessed without authentication."
|
||||
|
|
@ -26754,7 +26754,7 @@ msgstr "این سایت در حالت توسعه دهنده در حال اجرا
|
|||
|
||||
#: frappe/www/attribution.html:11
|
||||
msgid "This software is built on top of many open source packages."
|
||||
msgstr ""
|
||||
msgstr "این نرمافزار بر پایه بسیاری از بستههای نرمافزاری متنباز ساخته شده است."
|
||||
|
||||
#: frappe/website/doctype/web_page/web_page.js:71
|
||||
msgid "This title will be used as the title of the webpage as well as in meta tags"
|
||||
|
|
@ -30107,7 +30107,7 @@ msgstr "همچنین میتوانید این {0} را در مرورگر خو
|
|||
|
||||
#: frappe/templates/emails/user_invitation_expired.html:8
|
||||
msgid "You can ask your team to resend the invitation if you'd still like to join."
|
||||
msgstr ""
|
||||
msgstr "اگر هنوز مایل به عضویت هستید، میتوانید از تیم خود بخواهید که دعوتنامه را دوباره ارسال کند."
|
||||
|
||||
#: frappe/core/page/permission_manager/permission_manager_help.html:17
|
||||
msgid "You can change Submitted documents by cancelling them and then, amending them."
|
||||
|
|
@ -30250,7 +30250,7 @@ msgstr ""
|
|||
|
||||
#: frappe/database/query.py:810
|
||||
msgid "You do not have permission to access field: {0}"
|
||||
msgstr ""
|
||||
msgstr "شما اجازه دسترسی به فیلد را ندارید: {0}"
|
||||
|
||||
#: frappe/desk/query_report.py:934
|
||||
msgid "You do not have permission to access {0}: {1}."
|
||||
|
|
@ -30459,15 +30459,15 @@ msgstr "شما هدایت خواهید شد به:"
|
|||
|
||||
#: frappe/core/doctype/user_invitation/user_invitation.py:113
|
||||
msgid "You've been invited to join {0}"
|
||||
msgstr ""
|
||||
msgstr "از شما دعوت شده است تا به {0} بپیوندید"
|
||||
|
||||
#: frappe/templates/emails/user_invitation.html:5
|
||||
msgid "You've been invited to join {0}."
|
||||
msgstr ""
|
||||
msgstr "از شما دعوت شده است تا به {0} بپیوندید."
|
||||
|
||||
#: frappe/public/js/frappe/desk.js:547
|
||||
msgid "You've logged in as another user from another tab. Refresh this page to continue using system."
|
||||
msgstr ""
|
||||
msgstr "شما به عنوان یک کاربر دیگر از یک تب دیگر وارد سیستم شدهاید. برای ادامه استفاده از سیستم، این صفحه را رفرش کنید."
|
||||
|
||||
#: frappe/public/js/frappe/ui/toolbar/about.js:11
|
||||
msgid "YouTube"
|
||||
|
|
@ -30536,11 +30536,11 @@ msgstr "فرم شما با موفقیت به روز شد"
|
|||
|
||||
#: frappe/templates/emails/user_invitation_cancelled.html:5
|
||||
msgid "Your invitation to join {0} has been cancelled by the site administrator."
|
||||
msgstr ""
|
||||
msgstr "دعوت شما برای عضویت {0} توسط مدیر سایت لغو شده است."
|
||||
|
||||
#: frappe/templates/emails/user_invitation_expired.html:5
|
||||
msgid "Your invitation to join {0} has expired."
|
||||
msgstr ""
|
||||
msgstr "دعوت شما برای عضویت {0} منقضی شده است."
|
||||
|
||||
#: frappe/templates/emails/new_user.html:6
|
||||
msgid "Your login id is"
|
||||
|
|
@ -30566,7 +30566,7 @@ msgstr "پرسمان شما دریافت شد. ما به زودی پاسخ خو
|
|||
|
||||
#: frappe/desk/query_report.py:342 frappe/desk/reportview.py:402
|
||||
msgid "Your report is being generated in the background. You will receive an email on {0} with a download link once it is ready."
|
||||
msgstr ""
|
||||
msgstr "گزارش شما در پسزمینه در حال تولید است. به محض آماده شدن، ایمیلی حاوی لینک دانلود در {0} دریافت خواهید کرد."
|
||||
|
||||
#: frappe/app.py:377
|
||||
msgid "Your session has expired, please login again to continue."
|
||||
|
|
@ -31858,7 +31858,7 @@ msgstr "{0} رکورد برونبُرد خواهد شد"
|
|||
|
||||
#: frappe/public/js/frappe/form/footer/version_timeline_content_builder.js:313
|
||||
msgid "{0} removed 1 row from {1}"
|
||||
msgstr ""
|
||||
msgstr "{0} ۱ ردیف از {1} حذف کرد"
|
||||
|
||||
#: frappe/public/js/frappe/form/footer/form_timeline.js:420
|
||||
msgctxt "Form timeline"
|
||||
|
|
@ -31871,7 +31871,7 @@ msgstr "{0} تخصیص خود را حذف کرد."
|
|||
|
||||
#: frappe/public/js/frappe/form/footer/version_timeline_content_builder.js:291
|
||||
msgid "{0} removed {1} rows from {2}"
|
||||
msgstr ""
|
||||
msgstr "{0} {1} ردیف از {2} حذف کرد"
|
||||
|
||||
#: frappe/public/js/frappe/roles_editor.js:64
|
||||
msgid "{0} role does not have permission on any doctype"
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -3,7 +3,7 @@ msgstr ""
|
|||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: developers@frappe.io\n"
|
||||
"POT-Creation-Date: 2025-11-30 09:34+0000\n"
|
||||
"PO-Revision-Date: 2025-12-03 15:04\n"
|
||||
"PO-Revision-Date: 2025-12-07 17:11\n"
|
||||
"Last-Translator: developers@frappe.io\n"
|
||||
"Language-Team: Slovenian\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
@ -775,40 +775,42 @@ msgstr "Polje z imenom {0} že obstaja v {1}"
|
|||
|
||||
#: frappe/core/doctype/file/file.py:269
|
||||
msgid "A file with same name {} already exists"
|
||||
msgstr ""
|
||||
msgstr "Datoteka z istim imenom {} že obstaja"
|
||||
|
||||
#. Description of the 'Scopes' (Text) field in DocType 'OAuth Client'
|
||||
#: frappe/integrations/doctype/oauth_client/oauth_client.json
|
||||
msgid "A list of resources which the Client App will have access to after the user allows it.<br> e.g. project"
|
||||
msgstr ""
|
||||
msgstr "Seznam virov, do katerih bo imela odjemalska aplikacija dostop, ko uporabnik to dovoli.<br> npr. projekt"
|
||||
|
||||
#: frappe/templates/emails/new_user.html:5
|
||||
msgid "A new account has been created for you at {0}"
|
||||
msgstr ""
|
||||
msgstr "Za vas je bil ustvarjen nov račun na {0}"
|
||||
|
||||
#: frappe/automation/doctype/auto_repeat/auto_repeat.py:431
|
||||
msgid "A recurring {0} {1} has been created for you via Auto Repeat {2}."
|
||||
msgstr ""
|
||||
msgstr "Ponavljajoči se {0} {1} je bil za vas ustvarjen prek storitve Samodejno ponavljanje {2}."
|
||||
|
||||
#. Description of the 'Symbol' (Data) field in DocType 'Currency'
|
||||
#: frappe/geo/doctype/currency/currency.json
|
||||
msgid "A symbol for this currency. For e.g. $"
|
||||
msgstr ""
|
||||
msgstr "Simbol za to valuto. Npr. $"
|
||||
|
||||
#: frappe/printing/doctype/print_format_field_template/print_format_field_template.py:49
|
||||
msgid "A template already exists for field {0} of {1}"
|
||||
msgstr ""
|
||||
msgstr "Predloga za polje {0} od {1} že obstaja"
|
||||
|
||||
#. Description of the 'Software Version' (Data) field in DocType 'OAuth Client'
|
||||
#: frappe/integrations/doctype/oauth_client/oauth_client.json
|
||||
msgid "A version identifier string for the client software.\n"
|
||||
"<br>\n"
|
||||
"The value of the should change on any update of the client software with the same Software ID."
|
||||
msgstr ""
|
||||
msgstr "Niz identifikatorja različice za odjemalsko programsko opremo.\n"
|
||||
"<br>\n"
|
||||
"Vrednost se mora spremeniti ob vsaki posodobitvi odjemalske programske opreme z istim identifikatorjem programske opreme."
|
||||
|
||||
#: frappe/utils/password_strength.py:169
|
||||
msgid "A word by itself is easy to guess."
|
||||
msgstr ""
|
||||
msgstr "Besedo samo po sebi je enostavno uganiti."
|
||||
|
||||
#. Option for the 'PDF Page Size' (Select) field in DocType 'Print Settings'
|
||||
#: frappe/printing/doctype/print_settings/print_settings.json
|
||||
|
|
@ -883,7 +885,7 @@ msgstr "Končna točka API"
|
|||
#. Label of the api_endpoint_args (Code) field in DocType 'Social Login Key'
|
||||
#: frappe/integrations/doctype/social_login_key/social_login_key.json
|
||||
msgid "API Endpoint Args"
|
||||
msgstr ""
|
||||
msgstr "Končne točke API Args"
|
||||
|
||||
#: frappe/integrations/doctype/social_login_key/social_login_key.py:102
|
||||
msgid "API Endpoint Args should be valid JSON"
|
||||
|
|
@ -1579,7 +1581,7 @@ msgstr ""
|
|||
|
||||
#: frappe/contacts/doctype/address/address.py:205
|
||||
msgid "Addresses"
|
||||
msgstr ""
|
||||
msgstr "Naslovi"
|
||||
|
||||
#. Name of a report
|
||||
#: frappe/contacts/report/addresses_and_contacts/addresses_and_contacts.json
|
||||
|
|
@ -2005,7 +2007,7 @@ msgstr ""
|
|||
#. Label of the allow_events_in_timeline (Check) field in DocType 'DocType'
|
||||
#: frappe/core/doctype/doctype/doctype.json
|
||||
msgid "Allow events in timeline"
|
||||
msgstr ""
|
||||
msgstr "Dovoli dogodke na časovnici"
|
||||
|
||||
#. Label of the allow_in_quick_entry (Check) field in DocType 'DocField'
|
||||
#. Label of the allow_in_quick_entry (Check) field in DocType 'Custom Field'
|
||||
|
|
@ -2020,12 +2022,12 @@ msgstr "Dovoli v Hitrem Vnosu"
|
|||
#. Label of the allow_incomplete (Check) field in DocType 'Web Form'
|
||||
#: frappe/website/doctype/web_form/web_form.json
|
||||
msgid "Allow incomplete forms"
|
||||
msgstr ""
|
||||
msgstr "Dovoli nepopolne obrazce"
|
||||
|
||||
#. Label of the allow_multiple (Check) field in DocType 'Web Form'
|
||||
#: frappe/website/doctype/web_form/web_form.json
|
||||
msgid "Allow multiple responses"
|
||||
msgstr ""
|
||||
msgstr "Dovoli več odgovorov"
|
||||
|
||||
#. Label of the allow_on_submit (Check) field in DocType 'DocField'
|
||||
#. Label of the allow_on_submit (Check) field in DocType 'Custom Field'
|
||||
|
|
@ -2040,13 +2042,13 @@ msgstr "Dovoli ob Oddaji"
|
|||
#. Settings'
|
||||
#: frappe/core/doctype/system_settings/system_settings.json
|
||||
msgid "Allow only one session per user"
|
||||
msgstr ""
|
||||
msgstr "Dovoli samo eno sejo na uporabnika"
|
||||
|
||||
#. Label of the allow_page_break_inside_tables (Check) field in DocType 'Print
|
||||
#. Settings'
|
||||
#: frappe/printing/doctype/print_settings/print_settings.json
|
||||
msgid "Allow page break inside tables"
|
||||
msgstr ""
|
||||
msgstr "Dovoli prelom strani znotraj tabel"
|
||||
|
||||
#. Label of the allow_print (Check) field in DocType 'Web Form'
|
||||
#: frappe/website/doctype/web_form/web_form.json
|
||||
|
|
@ -2055,27 +2057,27 @@ msgstr "Dovoli Tiskanje"
|
|||
|
||||
#: frappe/desk/page/setup_wizard/setup_wizard.js:431
|
||||
msgid "Allow recording my first session to improve user experience"
|
||||
msgstr ""
|
||||
msgstr "Dovoli snemanje moje prve seje za izboljšanje uporabniške izkušnje"
|
||||
|
||||
#. Description of the 'Allow incomplete forms' (Check) field in DocType 'Web
|
||||
#. Form'
|
||||
#: frappe/website/doctype/web_form/web_form.json
|
||||
msgid "Allow saving if mandatory fields are not filled"
|
||||
msgstr ""
|
||||
msgstr "Dovoli shranjevanje, če obvezna polja niso izpolnjena"
|
||||
|
||||
#: frappe/desk/page/setup_wizard/setup_wizard.js:424
|
||||
msgid "Allow sending usage data for improving applications"
|
||||
msgstr ""
|
||||
msgstr "Dovoli pošiljanje podatkov o uporabi za izboljšanje aplikacij"
|
||||
|
||||
#. Description of the 'Login After' (Int) field in DocType 'User'
|
||||
#: frappe/core/doctype/user/user.json
|
||||
msgid "Allow user to login only after this hour (0-24)"
|
||||
msgstr ""
|
||||
msgstr "Dovoli uporabniku prijavo šele po tej uri (0–24)"
|
||||
|
||||
#. Description of the 'Login Before' (Int) field in DocType 'User'
|
||||
#: frappe/core/doctype/user/user.json
|
||||
msgid "Allow user to login only before this hour (0-24)"
|
||||
msgstr ""
|
||||
msgstr "Dovoli uporabniku prijavo samo pred to uro (0–24)"
|
||||
|
||||
#. Description of the 'Login with email link' (Check) field in DocType 'System
|
||||
#. Settings'
|
||||
|
|
@ -2408,11 +2410,11 @@ msgstr ""
|
|||
#: frappe/email/doctype/email_account/email_account.json
|
||||
#: frappe/email/doctype/imap_folder/imap_folder.json
|
||||
msgid "Append To"
|
||||
msgstr ""
|
||||
msgstr "Dodaj k"
|
||||
|
||||
#: frappe/email/doctype/email_account/email_account.py:202
|
||||
msgid "Append To can be one of {0}"
|
||||
msgstr ""
|
||||
msgstr "Dodaj k je lahko eden od {0}"
|
||||
|
||||
#. Description of the 'Append To' (Link) field in DocType 'Email Account'
|
||||
#: frappe/email/doctype/email_account/email_account.json
|
||||
|
|
@ -2633,7 +2635,7 @@ msgstr ""
|
|||
#: frappe/core/doctype/document_naming_rule/document_naming_rule.js:16
|
||||
#: frappe/core/doctype/user_permission/user_permission_list.js:165
|
||||
msgid "Are you sure?"
|
||||
msgstr ""
|
||||
msgstr "Ste prepričani?"
|
||||
|
||||
#. Label of the arguments (Code) field in DocType 'RQ Job'
|
||||
#: frappe/core/doctype/rq_job/rq_job.json
|
||||
|
|
@ -2960,7 +2962,7 @@ msgstr ""
|
|||
#. Name of a DocType
|
||||
#: frappe/core/doctype/audit_trail/audit_trail.json
|
||||
msgid "Audit Trail"
|
||||
msgstr ""
|
||||
msgstr "Revizijska sled"
|
||||
|
||||
#. Label of the auth_url_data (Code) field in DocType 'Social Login Key'
|
||||
#: frappe/integrations/doctype/social_login_key/social_login_key.json
|
||||
|
|
@ -3054,7 +3056,7 @@ msgstr ""
|
|||
#. Label of the authorize_url (Data) field in DocType 'Social Login Key'
|
||||
#: frappe/integrations/doctype/social_login_key/social_login_key.json
|
||||
msgid "Authorize URL"
|
||||
msgstr ""
|
||||
msgstr "Avtoriziraj URL"
|
||||
|
||||
#. Option for the 'Status' (Select) field in DocType 'Integration Request'
|
||||
#: frappe/integrations/doctype/integration_request/integration_request.json
|
||||
|
|
@ -3096,7 +3098,7 @@ msgstr "Samodejno Ponavljanje"
|
|||
#. Name of a DocType
|
||||
#: frappe/automation/doctype/auto_repeat_day/auto_repeat_day.json
|
||||
msgid "Auto Repeat Day"
|
||||
msgstr ""
|
||||
msgstr "Dan samodejnega ponavljanja"
|
||||
|
||||
#: frappe/automation/doctype/auto_repeat/auto_repeat.py:173
|
||||
msgid "Auto Repeat Day{0} {1} has been repeated."
|
||||
|
|
@ -3190,13 +3192,13 @@ msgstr ""
|
|||
#. 'Communication'
|
||||
#: frappe/core/doctype/communication/communication.json
|
||||
msgid "Automated Message"
|
||||
msgstr ""
|
||||
msgstr "Samodejno sporočilo"
|
||||
|
||||
#. Option for the 'Desk Theme' (Select) field in DocType 'User'
|
||||
#: frappe/core/doctype/user/user.json
|
||||
#: frappe/public/js/frappe/ui/theme_switcher.js:69
|
||||
msgid "Automatic"
|
||||
msgstr ""
|
||||
msgstr "Samodejno"
|
||||
|
||||
#: frappe/email/doctype/email_account/email_account.py:772
|
||||
msgid "Automatic Linking can be activated only for one Email Account."
|
||||
|
|
@ -3275,7 +3277,7 @@ msgstr "Odlično, zdaj pa poskusite sami ustvariti vnos"
|
|||
#. Option for the 'Navbar Style' (Select) field in DocType 'Desktop Settings'
|
||||
#: frappe/desk/doctype/desktop_settings/desktop_settings.json
|
||||
msgid "Awesomebar"
|
||||
msgstr ""
|
||||
msgstr "Awesomebar"
|
||||
|
||||
#: frappe/public/js/frappe/utils/number_systems.js:9
|
||||
msgctxt "Number system"
|
||||
|
|
@ -3385,7 +3387,7 @@ msgstr "Slika Ozadja"
|
|||
#. Label of a chart in the System Workspace
|
||||
#: frappe/core/workspace/system/system.json
|
||||
msgid "Background Job Activity"
|
||||
msgstr ""
|
||||
msgstr "Dejavnost opravila v ozadju"
|
||||
|
||||
#. Label of a Link in the Build Workspace
|
||||
#. Label of the background_jobs_section (Section Break) field in DocType
|
||||
|
|
@ -3400,16 +3402,16 @@ msgstr "Ozadna Dela"
|
|||
#. Report'
|
||||
#: frappe/desk/doctype/system_health_report/system_health_report.json
|
||||
msgid "Background Jobs Check"
|
||||
msgstr ""
|
||||
msgstr "Preverjanje delovnih mest v ozadju"
|
||||
|
||||
#. Label of the background_jobs_queue (Autocomplete) field in DocType 'Webhook'
|
||||
#: frappe/integrations/doctype/webhook/webhook.json
|
||||
msgid "Background Jobs Queue"
|
||||
msgstr ""
|
||||
msgstr "Čakalna vrsta opravil v ozadju"
|
||||
|
||||
#: frappe/public/js/frappe/list/bulk_operations.js:87
|
||||
msgid "Background Print (required for >25 documents)"
|
||||
msgstr ""
|
||||
msgstr "Tisk v ozadju (potrebno za >25 dokumentov)"
|
||||
|
||||
#. Label of the background_workers (Section Break) field in DocType 'System
|
||||
#. Settings'
|
||||
|
|
@ -3418,7 +3420,7 @@ msgstr ""
|
|||
#: frappe/core/doctype/system_settings/system_settings.json
|
||||
#: frappe/desk/doctype/system_health_report/system_health_report.json
|
||||
msgid "Background Workers"
|
||||
msgstr ""
|
||||
msgstr "Delavci v ozadju"
|
||||
|
||||
#: frappe/desk/page/backups/backups.js:28
|
||||
msgid "Backup Encryption Key"
|
||||
|
|
@ -3578,26 +3580,26 @@ msgstr ""
|
|||
#. Option for the 'DocType Event' (Select) field in DocType 'Server Script'
|
||||
#: frappe/core/doctype/server_script/server_script.json
|
||||
msgid "Before Submit"
|
||||
msgstr ""
|
||||
msgstr "Pred Oddajo"
|
||||
|
||||
#. Option for the 'DocType Event' (Select) field in DocType 'Server Script'
|
||||
#: frappe/core/doctype/server_script/server_script.json
|
||||
msgid "Before Validate"
|
||||
msgstr ""
|
||||
msgstr "Pred Potrditvijo"
|
||||
|
||||
#. Option for the 'Level' (Select) field in DocType 'Help Article'
|
||||
#: frappe/website/doctype/help_article/help_article.json
|
||||
msgid "Beginner"
|
||||
msgstr ""
|
||||
msgstr "Začetnik"
|
||||
|
||||
#: frappe/public/js/frappe/form/link_selector.js:29
|
||||
msgid "Beginning with"
|
||||
msgstr ""
|
||||
msgstr "Začenši z"
|
||||
|
||||
#. Label of the beta (Check) field in DocType 'DocType'
|
||||
#: frappe/core/doctype/doctype/doctype.json
|
||||
msgid "Beta"
|
||||
msgstr ""
|
||||
msgstr "Beta"
|
||||
|
||||
#: frappe/utils/password_strength.py:73
|
||||
msgid "Better add a few more letters or another word"
|
||||
|
|
@ -3605,7 +3607,7 @@ msgstr ""
|
|||
|
||||
#: frappe/public/js/frappe/ui/filters/filter.js:27
|
||||
msgid "Between"
|
||||
msgstr ""
|
||||
msgstr "Med"
|
||||
|
||||
#. Option for the 'Address Type' (Select) field in DocType 'Address'
|
||||
#: frappe/contacts/doctype/address/address.json
|
||||
|
|
@ -3781,7 +3783,7 @@ msgstr ""
|
|||
#. Name of a Workspace
|
||||
#: frappe/core/workspace/build/build.json
|
||||
msgid "Build"
|
||||
msgstr ""
|
||||
msgstr "Zgradi"
|
||||
|
||||
#. Description of a Card Break in the Build Workspace
|
||||
#: frappe/core/workspace/build/build.json
|
||||
|
|
@ -3790,45 +3792,45 @@ msgstr ""
|
|||
|
||||
#: frappe/workflow/doctype/workflow/workflow_list.js:18
|
||||
msgid "Build {0}"
|
||||
msgstr ""
|
||||
msgstr "+ {0}"
|
||||
|
||||
#: frappe/templates/includes/footer/footer_powered.html:1
|
||||
msgid "Built on {0}"
|
||||
msgstr ""
|
||||
msgstr "Zgrajeno na {0}"
|
||||
|
||||
#. Label of the bulk_actions (Check) field in DocType 'User'
|
||||
#: frappe/core/doctype/user/user.json
|
||||
msgid "Bulk Actions"
|
||||
msgstr ""
|
||||
msgstr "Množična dejanja"
|
||||
|
||||
#: frappe/core/doctype/user_permission/user_permission_list.js:142
|
||||
msgid "Bulk Delete"
|
||||
msgstr ""
|
||||
msgstr "Množično brisanje"
|
||||
|
||||
#: frappe/public/js/frappe/list/bulk_operations.js:321
|
||||
msgid "Bulk Edit"
|
||||
msgstr ""
|
||||
msgstr "Množično urejanje"
|
||||
|
||||
#: frappe/public/js/frappe/form/grid.js:1211
|
||||
msgid "Bulk Edit {0}"
|
||||
msgstr ""
|
||||
msgstr "Množično urejanje {0}"
|
||||
|
||||
#: frappe/desk/reportview.py:643
|
||||
msgid "Bulk Operation Failed"
|
||||
msgstr ""
|
||||
msgstr "Množična operacija ni uspela"
|
||||
|
||||
#: frappe/desk/reportview.py:647
|
||||
msgid "Bulk Operation Successful"
|
||||
msgstr ""
|
||||
msgstr "Množična operacija je uspešna"
|
||||
|
||||
#: frappe/public/js/frappe/list/bulk_operations.js:131
|
||||
msgid "Bulk PDF Export"
|
||||
msgstr ""
|
||||
msgstr "Množično izvažanje PDF"
|
||||
|
||||
#. Name of a DocType
|
||||
#: frappe/desk/doctype/bulk_update/bulk_update.json
|
||||
msgid "Bulk Update"
|
||||
msgstr ""
|
||||
msgstr "Množična posodobitev"
|
||||
|
||||
#: frappe/model/workflow.py:310
|
||||
msgid "Bulk approval only support up to 500 documents."
|
||||
|
|
@ -3853,17 +3855,17 @@ msgstr ""
|
|||
#: frappe/custom/doctype/custom_field/custom_field.json
|
||||
#: frappe/custom/doctype/customize_form_field/customize_form_field.json
|
||||
msgid "Button"
|
||||
msgstr ""
|
||||
msgstr "Gumb"
|
||||
|
||||
#. Label of the button_gradients (Check) field in DocType 'Website Theme'
|
||||
#: frappe/website/doctype/website_theme/website_theme.json
|
||||
msgid "Button Gradients"
|
||||
msgstr ""
|
||||
msgstr "Gradienti gumbov"
|
||||
|
||||
#. Label of the button_rounded_corners (Check) field in DocType 'Website Theme'
|
||||
#: frappe/website/doctype/website_theme/website_theme.json
|
||||
msgid "Button Rounded Corners"
|
||||
msgstr ""
|
||||
msgstr "Zaobljeni vogali gumba"
|
||||
|
||||
#. Label of the button_shadows (Check) field in DocType 'Website Theme'
|
||||
#: frappe/website/doctype/website_theme/website_theme.json
|
||||
|
|
@ -3921,7 +3923,7 @@ msgstr ""
|
|||
|
||||
#: frappe/templates/print_formats/standard_macros.html:220
|
||||
msgid "CANCELLED"
|
||||
msgstr ""
|
||||
msgstr "ODKLICANO"
|
||||
|
||||
#. Label of the cc (Code) field in DocType 'Communication'
|
||||
#. Label of the cc (Code) field in DocType 'Notification Recipient'
|
||||
|
|
@ -4129,7 +4131,7 @@ msgstr ""
|
|||
#: frappe/public/js/frappe/model/indicator.js:78
|
||||
#: frappe/public/js/frappe/ui/filters/filter.js:540
|
||||
msgid "Cancelled"
|
||||
msgstr ""
|
||||
msgstr "Preklicano"
|
||||
|
||||
#: frappe/core/doctype/deleted_document/deleted_document.py:52
|
||||
msgid "Cancelled Document restored as Draft"
|
||||
|
|
@ -4392,24 +4394,24 @@ msgstr "Kartice"
|
|||
#: frappe/public/js/frappe/views/interaction.js:72
|
||||
#: frappe/website/doctype/help_article/help_article.json
|
||||
msgid "Category"
|
||||
msgstr ""
|
||||
msgstr "Kategorija"
|
||||
|
||||
#. Label of the category_description (Text) field in DocType 'Help Category'
|
||||
#: frappe/website/doctype/help_category/help_category.json
|
||||
msgid "Category Description"
|
||||
msgstr ""
|
||||
msgstr "Opis Kategorije"
|
||||
|
||||
#. Label of the category_name (Data) field in DocType 'Help Category'
|
||||
#: frappe/website/doctype/help_category/help_category.json
|
||||
msgid "Category Name"
|
||||
msgstr ""
|
||||
msgstr "Ime Kategorije"
|
||||
|
||||
#. Option for the 'Align' (Select) field in DocType 'Letter Head'
|
||||
#. Option for the 'Text Align' (Select) field in DocType 'Web Page'
|
||||
#: frappe/printing/doctype/letter_head/letter_head.json
|
||||
#: frappe/website/doctype/web_page/web_page.json
|
||||
msgid "Center"
|
||||
msgstr ""
|
||||
msgstr "Center"
|
||||
|
||||
#: frappe/core/page/permission_manager/permission_manager_help.html:16
|
||||
msgid "Certain documents, like an Invoice, should not be changed once final. The final state for such documents is called Submitted. You can restrict which roles can Submit."
|
||||
|
|
@ -4458,7 +4460,7 @@ msgstr ""
|
|||
#. Label of the changed_at (Datetime) field in DocType 'Permission Log'
|
||||
#: frappe/core/doctype/permission_log/permission_log.json
|
||||
msgid "Changed at"
|
||||
msgstr ""
|
||||
msgstr "Spremenjeno"
|
||||
|
||||
#. Label of the changed_by (Link) field in DocType 'Permission Log'
|
||||
#: frappe/core/doctype/permission_log/permission_log.json
|
||||
|
|
@ -4473,7 +4475,7 @@ msgstr ""
|
|||
#. Label of the changed_values (HTML) field in DocType 'Permission Log'
|
||||
#: frappe/core/doctype/permission_log/permission_log.json
|
||||
msgid "Changes"
|
||||
msgstr ""
|
||||
msgstr "Spremembe"
|
||||
|
||||
#: frappe/email/doctype/email_domain/email_domain.js:5
|
||||
msgid "Changing any setting will reflect on all the email accounts associated with this domain."
|
||||
|
|
@ -4518,25 +4520,25 @@ msgstr ""
|
|||
#. Label of the source (Link) field in DocType 'Dashboard Chart'
|
||||
#: frappe/desk/doctype/dashboard_chart/dashboard_chart.json
|
||||
msgid "Chart Source"
|
||||
msgstr ""
|
||||
msgstr "Vir Grafikona"
|
||||
|
||||
#. Label of the chart_type (Select) field in DocType 'Dashboard Chart'
|
||||
#: frappe/desk/doctype/dashboard_chart/dashboard_chart.json
|
||||
#: frappe/public/js/frappe/views/reports/report_view.js:510
|
||||
msgid "Chart Type"
|
||||
msgstr ""
|
||||
msgstr "Tip Grafikona"
|
||||
|
||||
#. Label of the charts (Table) field in DocType 'Dashboard'
|
||||
#. Label of the charts (Table) field in DocType 'Workspace'
|
||||
#: frappe/desk/doctype/dashboard/dashboard.json
|
||||
#: frappe/desk/doctype/workspace/workspace.json
|
||||
msgid "Charts"
|
||||
msgstr ""
|
||||
msgstr "Grafikoni"
|
||||
|
||||
#. Option for the 'Type' (Select) field in DocType 'Communication'
|
||||
#: frappe/core/doctype/communication/communication.json
|
||||
msgid "Chat"
|
||||
msgstr ""
|
||||
msgstr "Klepet"
|
||||
|
||||
#. Option for the 'Type' (Select) field in DocType 'DocField'
|
||||
#. Option for the 'Fieldtype' (Select) field in DocType 'Report Column'
|
||||
|
|
@ -4553,7 +4555,7 @@ msgstr ""
|
|||
#: frappe/website/doctype/web_form_field/web_form_field.json
|
||||
#: frappe/website/doctype/web_template_field/web_template_field.json
|
||||
msgid "Check"
|
||||
msgstr ""
|
||||
msgstr "Preveri"
|
||||
|
||||
#: frappe/integrations/doctype/webhook/webhook.py:99
|
||||
msgid "Check Request URL"
|
||||
|
|
@ -4611,12 +4613,12 @@ msgstr ""
|
|||
#. Label of the child_doctype (Data) field in DocType 'Form Tour Step'
|
||||
#: frappe/desk/doctype/form_tour_step/form_tour_step.json
|
||||
msgid "Child Doctype"
|
||||
msgstr ""
|
||||
msgstr "Podrejeni Doctype"
|
||||
|
||||
#. Label of the child (Check) field in DocType 'Workspace Sidebar Item'
|
||||
#: frappe/desk/doctype/workspace_sidebar_item/workspace_sidebar_item.json
|
||||
msgid "Child Item"
|
||||
msgstr ""
|
||||
msgstr "Podrejeni Artikel"
|
||||
|
||||
#: frappe/core/doctype/doctype/doctype.py:1647
|
||||
msgid "Child Table {0} for field {1} must be virtual"
|
||||
|
|
@ -4664,34 +4666,34 @@ msgstr ""
|
|||
#: frappe/contacts/report/addresses_and_contacts/addresses_and_contacts.py:39
|
||||
#: frappe/website/doctype/contact_us_settings/contact_us_settings.json
|
||||
msgid "City"
|
||||
msgstr ""
|
||||
msgstr "Mesto"
|
||||
|
||||
#. Label of the city (Data) field in DocType 'Address'
|
||||
#: frappe/contacts/doctype/address/address.json
|
||||
msgid "City/Town"
|
||||
msgstr ""
|
||||
msgstr "Mesto/Kraj"
|
||||
|
||||
#: frappe/core/doctype/recorder/recorder_list.js:12
|
||||
#: frappe/public/js/frappe/form/controls/attach.js:16
|
||||
msgid "Clear"
|
||||
msgstr ""
|
||||
msgstr "Počisti"
|
||||
|
||||
#: frappe/public/js/frappe/views/communication.js:429
|
||||
msgid "Clear & Add Template"
|
||||
msgstr ""
|
||||
msgstr "Počisti & Dodaj Predlogo"
|
||||
|
||||
#: frappe/public/js/frappe/views/communication.js:105
|
||||
msgid "Clear & Add template"
|
||||
msgstr ""
|
||||
msgstr "Počisti & Dodaj Predlogo"
|
||||
|
||||
#: frappe/public/js/frappe/form/controls/multiselect_list.js:6
|
||||
msgid "Clear All"
|
||||
msgstr ""
|
||||
msgstr "Počisti vse"
|
||||
|
||||
#: frappe/public/js/frappe/list/list_view.js:2122
|
||||
msgctxt "Button in list view actions menu"
|
||||
msgid "Clear Assignment"
|
||||
msgstr ""
|
||||
msgstr "Počisti dodelitev"
|
||||
|
||||
#: frappe/public/js/frappe/ui/keyboard.js:287
|
||||
msgid "Clear Cache and Reload"
|
||||
|
|
@ -4732,7 +4734,7 @@ msgstr ""
|
|||
|
||||
#: frappe/website/doctype/web_form/templates/web_form.html:154
|
||||
msgid "Click here"
|
||||
msgstr ""
|
||||
msgstr "Klikni tukaj"
|
||||
|
||||
#: frappe/public/js/frappe/file_uploader/FileUploader.vue:539
|
||||
msgid "Click on a file to select it."
|
||||
|
|
@ -4892,7 +4894,7 @@ msgstr ""
|
|||
#: frappe/public/js/frappe/ui/messages.js:251
|
||||
#: frappe/website/js/bootstrap-4.js:24
|
||||
msgid "Close"
|
||||
msgstr ""
|
||||
msgstr "Zapri"
|
||||
|
||||
#. Label of the close_condition (Code) field in DocType 'Assignment Rule'
|
||||
#: frappe/automation/doctype/assignment_rule/assignment_rule.json
|
||||
|
|
@ -4911,7 +4913,7 @@ msgstr ""
|
|||
#: frappe/core/doctype/communication/communication.json
|
||||
#: frappe/desk/doctype/event/event.json frappe/desk/doctype/todo/todo.json
|
||||
msgid "Closed"
|
||||
msgstr ""
|
||||
msgstr "Zaprto"
|
||||
|
||||
#: frappe/templates/discussions/comment_box.html:25
|
||||
#: frappe/templates/discussions/reply_section.html:53
|
||||
|
|
@ -4930,7 +4932,7 @@ msgstr ""
|
|||
#: frappe/geo/doctype/country/country.json
|
||||
#: frappe/integrations/doctype/oauth_client/oauth_client.json
|
||||
msgid "Code"
|
||||
msgstr ""
|
||||
msgstr "Koda"
|
||||
|
||||
#. Label of the code_challenge (Data) field in DocType 'OAuth Authorization
|
||||
#. Code'
|
||||
|
|
@ -5024,7 +5026,7 @@ msgstr ""
|
|||
#: frappe/website/doctype/social_link_settings/social_link_settings.json
|
||||
#: frappe/website/doctype/web_form_field/web_form_field.json
|
||||
msgid "Color"
|
||||
msgstr ""
|
||||
msgstr "Barva"
|
||||
|
||||
#. Label of the column (Data) field in DocType 'Recorder Suggested Index'
|
||||
#: frappe/core/doctype/recorder_suggested_index/recorder_suggested_index.json
|
||||
|
|
@ -5032,19 +5034,19 @@ msgstr ""
|
|||
#: frappe/public/js/form_builder/components/Section.vue:270
|
||||
#: frappe/public/js/print_format_builder/ConfigureColumns.vue:8
|
||||
msgid "Column"
|
||||
msgstr ""
|
||||
msgstr "Stolpec"
|
||||
|
||||
#: frappe/core/doctype/report/boilerplate/controller.py:28
|
||||
msgid "Column 1"
|
||||
msgstr ""
|
||||
msgstr "Stolpec 1"
|
||||
|
||||
#: frappe/core/doctype/report/boilerplate/controller.py:33
|
||||
msgid "Column 2"
|
||||
msgstr ""
|
||||
msgstr "Stolpec 2"
|
||||
|
||||
#: frappe/desk/doctype/kanban_board/kanban_board.py:84
|
||||
msgid "Column <b>{0}</b> already exist."
|
||||
msgstr ""
|
||||
msgstr "Stolpec <b>{0}</b> že obstaja."
|
||||
|
||||
#. Option for the 'Type' (Select) field in DocType 'DocField'
|
||||
#. Option for the 'Field Type' (Select) field in DocType 'Custom Field'
|
||||
|
|
@ -5057,17 +5059,17 @@ msgstr ""
|
|||
#: frappe/website/doctype/web_form_field/web_form_field.json
|
||||
#: frappe/website/doctype/web_template_field/web_template_field.json
|
||||
msgid "Column Break"
|
||||
msgstr ""
|
||||
msgstr "Prelom Stolpca"
|
||||
|
||||
#: frappe/core/doctype/data_export/exporter.py:140
|
||||
msgid "Column Labels:"
|
||||
msgstr ""
|
||||
msgstr "Oznake Stolpcev:"
|
||||
|
||||
#. Label of the column_name (Data) field in DocType 'Kanban Board Column'
|
||||
#: frappe/core/doctype/data_export/exporter.py:25
|
||||
#: frappe/desk/doctype/kanban_board_column/kanban_board_column.json
|
||||
msgid "Column Name"
|
||||
msgstr ""
|
||||
msgstr "Ime Stolpca"
|
||||
|
||||
#: frappe/desk/doctype/kanban_board/kanban_board.py:45
|
||||
msgid "Column Name cannot be empty"
|
||||
|
|
@ -5115,7 +5117,7 @@ msgstr ""
|
|||
#. Option for the 'PDF Page Size' (Select) field in DocType 'Print Settings'
|
||||
#: frappe/printing/doctype/print_settings/print_settings.json
|
||||
msgid "Comm10E"
|
||||
msgstr ""
|
||||
msgstr "Comm10E"
|
||||
|
||||
#. Name of a DocType
|
||||
#. Option for the 'Comment Type' (Select) field in DocType 'Comment'
|
||||
|
|
@ -5125,7 +5127,7 @@ msgstr ""
|
|||
#: frappe/public/js/frappe/form/sidebar/assign_to.js:237
|
||||
#: frappe/templates/includes/comments/comments.html:34
|
||||
msgid "Comment"
|
||||
msgstr ""
|
||||
msgstr "Komentar"
|
||||
|
||||
#. Label of the comment_by (Data) field in DocType 'Comment'
|
||||
#: frappe/core/doctype/comment/comment.json
|
||||
|
|
@ -8426,7 +8428,7 @@ msgstr ""
|
|||
|
||||
#: frappe/public/js/frappe/form/grid_row_form.js:42
|
||||
msgid "ESC"
|
||||
msgstr ""
|
||||
msgstr "ESC"
|
||||
|
||||
#. Option for the 'Comment Type' (Select) field in DocType 'Comment'
|
||||
#: frappe/core/doctype/comment/comment.json
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ msgstr ""
|
|||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: developers@frappe.io\n"
|
||||
"POT-Creation-Date: 2025-11-30 09:34+0000\n"
|
||||
"PO-Revision-Date: 2025-12-02 14:59\n"
|
||||
"PO-Revision-Date: 2025-12-07 17:11\n"
|
||||
"Last-Translator: developers@frappe.io\n"
|
||||
"Language-Team: Swedish\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
@ -3796,7 +3796,7 @@ msgstr "Skapa {0}"
|
|||
|
||||
#: frappe/templates/includes/footer/footer_powered.html:1
|
||||
msgid "Built on {0}"
|
||||
msgstr "Skapad av{0}"
|
||||
msgstr "Skapad av {0}"
|
||||
|
||||
#. Label of the bulk_actions (Check) field in DocType 'User'
|
||||
#: frappe/core/doctype/user/user.json
|
||||
|
|
|
|||
|
|
@ -200,8 +200,7 @@ class DatabaseQuery:
|
|||
query = frappe.qb.get_query(**kwargs)
|
||||
|
||||
if not run:
|
||||
# Return the SQL query string instead of executing
|
||||
return str(query.get_sql())
|
||||
return query
|
||||
|
||||
# Run the query
|
||||
if pluck:
|
||||
|
|
|
|||
|
|
@ -1900,14 +1900,18 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList {
|
|||
|
||||
get_search_params() {
|
||||
let search_params = new URLSearchParams();
|
||||
|
||||
this.get_filters_for_args().forEach((filter) => {
|
||||
if (filter[2] === "=") {
|
||||
search_params.append(filter[1], filter[3]);
|
||||
} else {
|
||||
search_params.append(filter[1], JSON.stringify([filter[2], filter[3]]));
|
||||
}
|
||||
const doctype = filter[0];
|
||||
const field = filter[1];
|
||||
const operator = filter[2];
|
||||
const value = filter[3];
|
||||
|
||||
const query_key = doctype === this.doctype ? field : `${doctype}.${field}`;
|
||||
const query_value = operator === "=" ? value : JSON.stringify([operator, value]);
|
||||
|
||||
search_params.append(query_key, query_value);
|
||||
});
|
||||
|
||||
return search_params;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -161,11 +161,11 @@ frappe.ui.Sidebar = class Sidebar {
|
|||
let match = false;
|
||||
const that = this;
|
||||
$(".item-anchor").each(function () {
|
||||
let href = $(this).attr("href")?.split("?")[0];
|
||||
let href = decodeURIComponent($(this).attr("href")?.split("?")[0]);
|
||||
const path = decodeURIComponent(window.location.pathname);
|
||||
|
||||
// Match only if path equals href or starts with it followed by "/" or end of string
|
||||
const isActive = new RegExp(`^${href}(?:/|$)`).test(path);
|
||||
const isActive = href === path;
|
||||
if (href && isActive) {
|
||||
match = true;
|
||||
if (that.active_item) that.active_item.removeClass("active-sidebar");
|
||||
|
|
@ -445,7 +445,7 @@ frappe.ui.Sidebar = class Sidebar {
|
|||
if (route.length == 2) {
|
||||
workspace_title = this.get_correct_workspace_sidebars(route[1]);
|
||||
} else {
|
||||
workspace_title = this.get_correct_workspace_sidebars(route);
|
||||
workspace_title = this.get_correct_workspace_sidebars(route[0]);
|
||||
}
|
||||
let module_name = workspace_title[0];
|
||||
if (module_name) {
|
||||
|
|
|
|||
|
|
@ -54,14 +54,16 @@ frappe.ui.sidebar_item.TypeLink = class SidebarItem {
|
|||
});
|
||||
}
|
||||
}
|
||||
return path;
|
||||
if (path) {
|
||||
return encodeURI(path);
|
||||
}
|
||||
}
|
||||
prepare() {}
|
||||
make() {
|
||||
this.path = this.get_path();
|
||||
this.set_suffix();
|
||||
if (!this.item.icon && !(this.item.child && this.item.parent.indent)) {
|
||||
this.item.icon = "list-alt";
|
||||
this.item.icon = "list";
|
||||
}
|
||||
this.wrapper = $(
|
||||
frappe.render_template("sidebar_item", {
|
||||
|
|
|
|||
|
|
@ -1754,10 +1754,19 @@ Object.assign(frappe.utils, {
|
|||
// don't remove unless patch is created to convert all existing filters from object to array
|
||||
// backward compatibility
|
||||
if (Array.isArray(filters_json)) {
|
||||
let filter = {};
|
||||
filters_json.forEach((arr) => {
|
||||
filter[arr[1]] = [arr[2], arr[3]];
|
||||
});
|
||||
let filter = filters_json.reduce((acc, filter) => {
|
||||
const field = filter[1];
|
||||
const value = [filter[2], filter[3]];
|
||||
|
||||
// if we have multiple filters for the same field,
|
||||
// we convert it into an array
|
||||
if (acc[field]) {
|
||||
acc[field].push(value);
|
||||
} else {
|
||||
acc[field] = [value];
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
return filter || [];
|
||||
}
|
||||
return filters_json || [];
|
||||
|
|
|
|||
|
|
@ -1047,28 +1047,32 @@ class TestDBQuery(IntegrationTestCase):
|
|||
self.assertIn("count", result[0])
|
||||
|
||||
def test_coalesce_with_in_ops(self):
|
||||
self.assertNotIn("IF", frappe.get_all("User", {"first_name": ("in", ["a", "b"])}, run=0))
|
||||
self.assertIn("IFNULL", frappe.get_all("User", {"first_name": ("in", ["a", None])}, run=0))
|
||||
self.assertIn("IFNULL", frappe.get_all("User", {"first_name": ("in", ["a", ""])}, run=0))
|
||||
self.assertIn("IFNULL", frappe.get_all("User", {"first_name": ("in", [])}, run=0))
|
||||
self.assertIn("IFNULL", frappe.get_all("User", {"first_name": ("not in", ["a"])}, run=0))
|
||||
self.assertIn("IFNULL", frappe.get_all("User", {"first_name": ("not in", [])}, run=0))
|
||||
self.assertIn("IFNULL", frappe.get_all("User", {"first_name": ("not in", [""])}, run=0))
|
||||
self.assertNotIn("IF", frappe.get_all("User", {"first_name": ("in", ["a", "b"])}, run=0).get_sql())
|
||||
self.assertIn("IFNULL", frappe.get_all("User", {"first_name": ("in", ["a", None])}, run=0).get_sql())
|
||||
self.assertIn("IFNULL", frappe.get_all("User", {"first_name": ("in", ["a", ""])}, run=0).get_sql())
|
||||
self.assertIn("IFNULL", frappe.get_all("User", {"first_name": ("in", [])}, run=0).get_sql())
|
||||
self.assertIn("IFNULL", frappe.get_all("User", {"first_name": ("not in", ["a"])}, run=0).get_sql())
|
||||
self.assertIn("IFNULL", frappe.get_all("User", {"first_name": ("not in", [])}, run=0).get_sql())
|
||||
self.assertIn("IFNULL", frappe.get_all("User", {"first_name": ("not in", [""])}, run=0).get_sql())
|
||||
|
||||
# primary key is never nullable
|
||||
self.assertNotIn("IFNULL", frappe.get_all("User", {"name": ("in", ["a", None])}, run=0))
|
||||
self.assertNotIn("IFNULL", frappe.get_all("User", {"name": ("in", ["a", ""])}, run=0))
|
||||
self.assertNotIn("IFNULL", frappe.get_all("User", {"name": ("in", (""))}, run=0))
|
||||
self.assertNotIn("IFNULL", frappe.get_all("User", {"name": ("in", ())}, run=0))
|
||||
self.assertNotIn("IFNULL", frappe.get_all("User", {"name": ("in", ["a", None])}, run=0).get_sql())
|
||||
self.assertNotIn("IFNULL", frappe.get_all("User", {"name": ("in", ["a", ""])}, run=0).get_sql())
|
||||
self.assertNotIn("IFNULL", frappe.get_all("User", {"name": ("in", (""))}, run=0).get_sql())
|
||||
self.assertNotIn("IFNULL", frappe.get_all("User", {"name": ("in", ())}, run=0).get_sql())
|
||||
|
||||
def test_coalesce_with_datetime_ops(self):
|
||||
self.assertNotIn("IFNULL", frappe.get_all("User", {"last_active": (">", "2022-01-01")}, run=0))
|
||||
self.assertNotIn("IFNULL", frappe.get_all("User", {"creation": ("<", "2022-01-01")}, run=0))
|
||||
self.assertNotIn(
|
||||
"IFNULL", frappe.get_all("User", {"last_active": (">", "2022-01-01")}, run=0).get_sql()
|
||||
)
|
||||
self.assertNotIn("IFNULL", frappe.get_all("User", {"creation": ("<", "2022-01-01")}, run=0).get_sql())
|
||||
self.assertNotIn(
|
||||
"IFNULL",
|
||||
frappe.get_all("User", {"last_active": ("between", ("2022-01-01", "2023-01-01"))}, run=0),
|
||||
frappe.get_all(
|
||||
"User", {"last_active": ("between", ("2022-01-01", "2023-01-01"))}, run=0
|
||||
).get_sql(),
|
||||
)
|
||||
self.assertIn("IFNULL", frappe.get_all("User", {"last_active": ("<", "2022-01-01")}, run=0))
|
||||
self.assertIn("IFNULL", frappe.get_all("User", {"last_active": ("<", "2022-01-01")}, run=0).get_sql())
|
||||
|
||||
def test_ambiguous_linked_tables(self):
|
||||
from frappe.desk.reportview import get
|
||||
|
|
@ -1145,16 +1149,16 @@ class TestDBQuery(IntegrationTestCase):
|
|||
self.assertEqual(count[1], frappe.db.count("Language"))
|
||||
|
||||
def test_ifnull_none(self):
|
||||
query = frappe.get_all("DocField", {"fieldname": None}, run=0)
|
||||
query = frappe.get_all("DocField", {"fieldname": None}, run=0).get_sql()
|
||||
self.assertIn("IS NULL", query)
|
||||
self.assertNotIn("\\'", query)
|
||||
self.assertNotIn("ifnull", query)
|
||||
self.assertFalse(frappe.get_all("DocField", {"name": None}))
|
||||
self.assertFalse(frappe.get_all("DocField", {"parent": None}))
|
||||
self.assertNotIn("0", frappe.get_all("DocField", {"parent": None}, run=0))
|
||||
self.assertNotIn("0", frappe.get_all("DocField", {"parent": None}, run=0).get_sql())
|
||||
|
||||
def test_ifnull_fallback_types(self):
|
||||
query = frappe.get_all("DocField", {"fieldname": ("!=", None)}, run=0)
|
||||
query = frappe.get_all("DocField", {"fieldname": ("!=", None)}, run=0).get_sql()
|
||||
# Fallbacks should always be of correct type
|
||||
self.assertIn("''", query)
|
||||
self.assertNotIn("0", query)
|
||||
|
|
|
|||
|
|
@ -285,10 +285,10 @@ class TestNestedSet(IntegrationTestCase):
|
|||
inclusive_link = {"link_field": ("descendants of (inclusive)", record)}
|
||||
|
||||
# db_query
|
||||
self.assertNotIn(record, frappe.get_all(TEST_DOCTYPE, exclusive_filter, run=0))
|
||||
self.assertIn(record, frappe.get_all(TEST_DOCTYPE, inclusive_filter, run=0))
|
||||
self.assertNotIn(record, frappe.get_all(linked_doctype, exclusive_link, run=0))
|
||||
self.assertIn(record, frappe.get_all(linked_doctype, inclusive_link, run=0))
|
||||
self.assertNotIn(record, frappe.get_all(TEST_DOCTYPE, exclusive_filter, run=0).get_sql())
|
||||
self.assertIn(record, frappe.get_all(TEST_DOCTYPE, inclusive_filter, run=0).get_sql())
|
||||
self.assertNotIn(record, frappe.get_all(linked_doctype, exclusive_link, run=0).get_sql())
|
||||
self.assertIn(record, frappe.get_all(linked_doctype, inclusive_link, run=0).get_sql())
|
||||
|
||||
# QB
|
||||
self.assertNotIn(record, str(frappe.qb.get_query(TEST_DOCTYPE, filters=exclusive_filter)))
|
||||
|
|
|
|||
|
|
@ -179,7 +179,7 @@ class TestPerformance(IntegrationTestCase):
|
|||
frappe.get_list("User")
|
||||
|
||||
def test_no_ifnull_checks(self):
|
||||
query = frappe.get_all("DocType", {"autoname": ("is", "set")}, run=0).lower()
|
||||
query = frappe.get_all("DocType", {"autoname": ("is", "set")}, run=0).get_sql().lower()
|
||||
self.assertNotIn("coalesce", query)
|
||||
self.assertNotIn("ifnull", query)
|
||||
|
||||
|
|
|
|||
|
|
@ -1902,6 +1902,30 @@ class TestQuery(IntegrationTestCase):
|
|||
# If we get here without PermissionError, the test passes
|
||||
self.assertIn(self.normalize_sql("GROUP BY `created_date`"), self.normalize_sql(sql))
|
||||
|
||||
def test_between_datetime_expansion(self):
|
||||
"""Test that date strings are expanded to datetime ranges for Datetime fields with 'between' operator"""
|
||||
# Test with creation field (standard datetime field)
|
||||
query = frappe.qb.get_query(
|
||||
"User",
|
||||
filters={"creation": ["between", ["2025-12-01", "2025-12-01"]]},
|
||||
)
|
||||
sql = query.get_sql()
|
||||
# Date strings should be expanded to datetime ranges
|
||||
self.assertIn("2025-12-01 00:00:00", sql)
|
||||
self.assertIn("2025-12-01 23:59:59", sql)
|
||||
|
||||
def test_timespan_datetime_expansion(self):
|
||||
"""Test that timespan operator expands dates to datetime ranges for Datetime fields"""
|
||||
query = frappe.qb.get_query(
|
||||
"User",
|
||||
filters={"creation": ["timespan", "last 7 days"]},
|
||||
)
|
||||
sql = query.get_sql()
|
||||
# Timespan should expand dates to datetime ranges (start of first day, end of last day)
|
||||
# Should have times like 00:00:00 and 23:59:59
|
||||
self.assertIn("00:00:00", sql)
|
||||
self.assertIn("23:59:59", sql)
|
||||
|
||||
|
||||
# This function is used as a permission query condition hook
|
||||
def test_permission_hook_condition(user):
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue