mirror of
https://github.com/frappe/erpnext.git
synced 2026-08-22 10:49:59 +00:00
Convert raw `frappe.db.sql` in the Setup, Utilities, Templates and Regional areas to `frappe.qb` / the ORM so the same code runs on MariaDB and Postgres. Behaviour is preserved on MariaDB; the conversions also make these paths valid under Postgres' stricter SQL (GROUP BY, case-sensitivity, reserved words). Conversions of note (behaviour kept identical to the MariaDB original): - email_digest: ToDo ordering replicated with a CASE that mirrors MySQL `field(priority,'High','Medium','Low')` (unknown/NULL -> 0, sorts first), NULL-date-first and a `name` tie-break for a deterministic LIMIT. - company.get_all_transactions_annual_history: the cross-DocType UNION + GROUP BY is replaced by one grouped query per DocType merged with a Counter, so two different DocTypes sharing a transaction_date still collapse into one bucket. - templates/utils.send_message: contact lookup wraps both sides in LOWER() to keep MariaDB's case-insensitive email match on case-sensitive Postgres. - regional/irs_1099 & uae_vat_201: address ranking and emirate aggregation rebuilt with CASE/aggregate selects that satisfy Postgres GROUP BY, with a deterministic tie-break on the LIMIT-1 address lookups. - utilities/product.get_item_codes_by_attributes: numeric attribute values are cast with cstr() so Postgres doesn't reject `varchar = numeric`. Tests (run on both MariaDB and Postgres, --lightmode): - New: company merge test, authorization_rule duplicate-check, youtube report, templates/utils, and utilities/templates page reports (partners, rfq, material_request_info, product, utilities __init__). - Existing suites kept green: company, email_digest, transaction_deletion_record, irs_1099, uae_vat_201. Deferred (tracked separately): - setup/doctype/authorization_control.py still has raw `.format()` SELECTs; left for its own PR. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
152 lines
4.0 KiB
Python
152 lines
4.0 KiB
Python
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
|
# License: GNU General Public License v3. See license.txt
|
|
|
|
|
|
import frappe
|
|
from frappe import _
|
|
from frappe.core.doctype.installed_applications.installed_applications import get_setup_wizard_completed_apps
|
|
|
|
import erpnext
|
|
|
|
|
|
def get_level(site_info):
|
|
activation_level = site_info.get("activation", {}).get("activation_level", 0)
|
|
sales_data = site_info.get("activation", {}).get("sales_data", [])
|
|
min_count = 0
|
|
doctypes = {
|
|
"Asset": 5,
|
|
"BOM": 3,
|
|
"Customer": 5,
|
|
"Delivery Note": 5,
|
|
"Employee": 3,
|
|
"Issue": 5,
|
|
"Item": 5,
|
|
"Journal Entry": 3,
|
|
"Lead": 3,
|
|
"Material Request": 5,
|
|
"Opportunity": 5,
|
|
"Payment Entry": 2,
|
|
"Project": 5,
|
|
"Purchase Order": 2,
|
|
"Purchase Invoice": 5,
|
|
"Purchase Receipt": 5,
|
|
"Quotation": 3,
|
|
"Sales Order": 2,
|
|
"Sales Invoice": 2,
|
|
"Stock Entry": 3,
|
|
"Supplier": 5,
|
|
"Task": 5,
|
|
"User": 5,
|
|
"Work Order": 5,
|
|
}
|
|
|
|
for doctype, min_count in doctypes.items():
|
|
count = frappe.db.count(doctype)
|
|
if count > min_count:
|
|
activation_level += 1
|
|
sales_data.append({doctype: count})
|
|
|
|
if "erpnext" in get_setup_wizard_completed_apps():
|
|
activation_level += 1
|
|
|
|
communication_number = frappe.db.count("Communication", dict(communication_medium="Email"))
|
|
if communication_number > 10:
|
|
activation_level += 1
|
|
sales_data.append({"Communication": communication_number})
|
|
|
|
# recent login
|
|
if frappe.db.exists(
|
|
"User", {"last_login": [">", frappe.utils.add_to_date(frappe.utils.now_datetime(), days=-2)]}
|
|
):
|
|
activation_level += 1
|
|
|
|
level = {"activation_level": activation_level, "sales_data": sales_data}
|
|
|
|
return level
|
|
|
|
|
|
def get_help_messages():
|
|
"""Returns help messages to be shown on Desktop"""
|
|
if get_level() > 6:
|
|
return []
|
|
|
|
domain = frappe.get_cached_value("Company", erpnext.get_default_company(), "domain")
|
|
messages = []
|
|
|
|
message_settings = [
|
|
frappe._dict(
|
|
doctype="Lead",
|
|
title=_("Create Leads"),
|
|
description=_("Leads help you get business, add all your contacts and more as your leads"),
|
|
action=_("Create Lead"),
|
|
route="List/Lead",
|
|
domain=("Manufacturing", "Retail", "Services", "Distribution"),
|
|
target=3,
|
|
),
|
|
frappe._dict(
|
|
doctype="Quotation",
|
|
title=_("Create customer quotes"),
|
|
description=_("Quotations are proposals, bids you have sent to your customers"),
|
|
action=_("Create Quotation"),
|
|
route="List/Quotation",
|
|
domain=("Manufacturing", "Retail", "Services", "Distribution"),
|
|
target=3,
|
|
),
|
|
frappe._dict(
|
|
doctype="Sales Order",
|
|
title=_("Manage your orders"),
|
|
description=_("Create Sales Orders to help you plan your work and deliver on-time"),
|
|
action=_("Create Sales Order"),
|
|
route="List/Sales Order",
|
|
domain=("Manufacturing", "Retail", "Services", "Distribution"),
|
|
target=3,
|
|
),
|
|
frappe._dict(
|
|
doctype="Purchase Order",
|
|
title=_("Create Purchase Orders"),
|
|
description=_("Purchase orders help you plan and follow up on your purchases"),
|
|
action=_("Create Purchase Order"),
|
|
route="List/Purchase Order",
|
|
domain=("Manufacturing", "Retail", "Services", "Distribution"),
|
|
target=3,
|
|
),
|
|
frappe._dict(
|
|
doctype="User",
|
|
title=_("Create Users"),
|
|
description=_(
|
|
"Add the rest of your organization as your users. You can also add invite Customers to your portal by adding them from Contacts"
|
|
),
|
|
action=_("Create User"),
|
|
route="List/User",
|
|
domain=("Manufacturing", "Retail", "Services", "Distribution"),
|
|
target=3,
|
|
),
|
|
frappe._dict(
|
|
doctype="Timesheet",
|
|
title=_("Add Timesheets"),
|
|
description=_(
|
|
"Timesheets help keep track of time, cost and billing for activities done by your team"
|
|
),
|
|
action=_("Create Timesheet"),
|
|
route="List/Timesheet",
|
|
domain=("Services",),
|
|
target=5,
|
|
),
|
|
frappe._dict(
|
|
doctype="Employee",
|
|
title=_("Create Employee Records"),
|
|
description=_("Create Employee records."),
|
|
action=_("Create Employee"),
|
|
route="List/Employee",
|
|
target=3,
|
|
),
|
|
]
|
|
|
|
for m in message_settings:
|
|
if not m.domain or domain in m.domain:
|
|
m.count = frappe.db.count(m.doctype)
|
|
if m.count < m.target:
|
|
messages.append(m)
|
|
|
|
return messages
|