Merge pull request #56439 from mihir-kandoi/migrate-request-type-json

fix!: switch ERPNext to JSON request body (use_json_request_body)
This commit is contained in:
Mihir Kandoi
2026-06-24 22:37:59 +05:30
committed by GitHub
76 changed files with 138 additions and 205 deletions

View File

@@ -137,7 +137,7 @@ def get_charts_for_country(country: str, with_standard: bool = False):
def _get_chart_name(content): def _get_chart_name(content):
if content: if content:
content = json.loads(content) content = frappe.parse_json(content)
if ( if (
content and content.get("disabled", "No") == "No" content and content.get("disabled", "No") == "No"
) or frappe.local.flags.allow_unverified_charts: ) or frappe.local.flags.allow_unverified_charts:

View File

@@ -224,7 +224,7 @@ def disable_dimension(doc: str):
def toggle_disabling(doc): def toggle_disabling(doc):
doc = json.loads(doc) doc = frappe.parse_json(doc)
if doc.get("disabled"): if doc.get("disabled"):
df = {"read_only": 1} df = {"read_only": 1}

View File

@@ -1058,9 +1058,9 @@ def get_auto_reconcile_message(partially_reconciled, reconciled):
@frappe.whitelist() @frappe.whitelist()
def reconcile_vouchers(bank_transaction_name: str | int, vouchers: str, is_new_voucher: bool = False): def reconcile_vouchers(bank_transaction_name: str | int, vouchers: str | list, is_new_voucher: bool = False):
# updated clear date of all the vouchers based on the bank transaction # updated clear date of all the vouchers based on the bank transaction
vouchers = json.loads(vouchers) vouchers = frappe.parse_json(vouchers)
transaction = frappe.get_doc("Bank Transaction", bank_transaction_name) transaction = frappe.get_doc("Bank Transaction", bank_transaction_name)
transaction.add_payment_entries(vouchers, is_new_voucher) transaction.add_payment_entries(vouchers, is_new_voucher)
transaction.validate_duplicate_references() transaction.validate_duplicate_references()

View File

@@ -290,7 +290,7 @@ def update_mapping_db(bank, template_options):
for d in bank.bank_transaction_mapping: for d in bank.bank_transaction_mapping:
d.delete() d.delete()
for d in json.loads(template_options)["column_to_field_map"].items(): for d in frappe.parse_json(template_options)["column_to_field_map"].items():
bank.append("bank_transaction_mapping", {"bank_transaction_field": d[1], "file_field": d[0]}) bank.append("bank_transaction_mapping", {"bank_transaction_field": d[1], "file_field": d[0]})
bank.save() bank.save()

View File

@@ -1183,8 +1183,7 @@ def update_pdf_tables(statement_import_id: str, tables: list | str):
if doc.status == "Completed": if doc.status == "Completed":
frappe.throw(_("This statement has already been imported."), title=_("Already Imported")) frappe.throw(_("This statement has already been imported."), title=_("Already Imported"))
if isinstance(tables, str): tables = frappe.parse_json(tables)
tables = json.loads(tables)
doc.apply_pdf_tables(tables) doc.apply_pdf_tables(tables)
@@ -1204,8 +1203,7 @@ def reextract_pdf_table(statement_import_id: str, page: int, table_index: int, b
if doc.status == "Completed": if doc.status == "Completed":
frappe.throw(_("This statement has already been imported."), title=_("Already Imported")) frappe.throw(_("This statement has already been imported."), title=_("Already Imported"))
if isinstance(bbox, str): bbox = frappe.parse_json(bbox)
bbox = json.loads(bbox)
page = int(page) page = int(page)
table_index = int(table_index) table_index = int(table_index)
@@ -1290,8 +1288,7 @@ def update_column_mapping(statement_import_id: str, column_mapping: list | str):
if doc.status == "Completed": if doc.status == "Completed":
frappe.throw(_("This statement has already been imported."), title=_("Already Imported")) frappe.throw(_("This statement has already been imported."), title=_("Already Imported"))
if isinstance(column_mapping, str): column_mapping = frappe.parse_json(column_mapping)
column_mapping = json.loads(column_mapping)
doc.apply_column_mapping(column_mapping) doc.apply_column_mapping(column_mapping)
doc.save() doc.save()

View File

@@ -35,12 +35,12 @@ def upload_bank_statement():
@frappe.whitelist() @frappe.whitelist()
def create_bank_entries(columns: str, data: str, bank_account: str): def create_bank_entries(columns: str, data: str | list, bank_account: str):
header_map = get_header_mapping(columns, bank_account) header_map = get_header_mapping(columns, bank_account)
success = 0 success = 0
errors = 0 errors = 0
for d in json.loads(data): for d in frappe.parse_json(data):
if all(item is None for item in d) is True: if all(item is None for item in d) is True:
continue continue
fields = {} fields = {}
@@ -66,7 +66,7 @@ def get_header_mapping(columns, bank_account):
mapping = get_bank_mapping(bank_account) mapping = get_bank_mapping(bank_account)
header_map = {} header_map = {}
for column in json.loads(columns): for column in frappe.parse_json(columns):
if column["content"] in mapping: if column["content"] in mapping:
header_map.update({mapping[column["content"]]: column["colIndex"]}) header_map.update({mapping[column["content"]]: column["colIndex"]})

View File

@@ -248,8 +248,7 @@ def get_dunning_letter_text(dunning_type: str, doc: str | dict, language: str |
DOCTYPE = "Dunning Letter Text" DOCTYPE = "Dunning Letter Text"
FIELDS = ["body_text", "closing_text", "language"] FIELDS = ["body_text", "closing_text", "language"]
if isinstance(doc, str): doc = frappe.parse_json(doc)
doc = json.loads(doc)
if not language: if not language:
language = doc.get("language") language = doc.get("language")

View File

@@ -1032,8 +1032,7 @@ class FormulaFieldUpdater:
def get_filtered_accounts(company: str, account_rows: str | list): def get_filtered_accounts(company: str, account_rows: str | list):
frappe.has_permission("Financial Report Template", ptype="read", throw=True) frappe.has_permission("Financial Report Template", ptype="read", throw=True)
if isinstance(account_rows, str): account_rows = [frappe._dict(row) for row in frappe.parse_json(account_rows)]
account_rows = json.loads(account_rows, object_hook=frappe._dict)
return DataCollector.get_filtered_accounts(company, account_rows) return DataCollector.get_filtered_accounts(company, account_rows)

View File

@@ -317,8 +317,8 @@ class InvoiceDiscounting(AccountsController):
@frappe.whitelist() @frappe.whitelist()
def get_invoices(filters: str): def get_invoices(filters: str | dict):
filters = frappe._dict(json.loads(filters)) filters = frappe._dict(frappe.parse_json(filters))
si = frappe.qb.DocType("Sales Invoice") si = frappe.qb.DocType("Sales Invoice")
di = frappe.qb.DocType("Discounted Invoice") di = frappe.qb.DocType("Discounted Invoice")

View File

@@ -1805,8 +1805,7 @@ class PaymentEntry(AccountsController):
if not self.references or not matched_payment_requests: if not self.references or not matched_payment_requests:
return return
if isinstance(matched_payment_requests, str): matched_payment_requests = frappe.parse_json(matched_payment_requests)
matched_payment_requests = json.loads(matched_payment_requests)
# modify matched_payment_requests # modify matched_payment_requests
# like (reference_doctype, reference_name, allocated_amount): payment_request # like (reference_doctype, reference_name, allocated_amount): payment_request
@@ -2011,8 +2010,7 @@ def validate_inclusive_tax(tax, doc):
@frappe.whitelist() @frappe.whitelist()
def get_outstanding_reference_documents(args: str | dict, validate: bool = False): def get_outstanding_reference_documents(args: str | dict, validate: bool = False):
if isinstance(args, str): args = frappe.parse_json(args)
args = json.loads(args)
if args.get("party_type") == "Member": if args.get("party_type") == "Member":
return return

View File

@@ -740,7 +740,7 @@ def make_payment_request(**args):
# Schedule-based PRs are allowed only if no Payment Entry exists for this document. # Schedule-based PRs are allowed only if no Payment Entry exists for this document.
# Any existing Payment Entry forces legacy (amount-based) flow. # Any existing Payment Entry forces legacy (amount-based) flow.
selected_payment_schedules = json.loads(args.get("schedules")) if args.get("schedules") else [] selected_payment_schedules = frappe.parse_json(args.get("schedules")) if args.get("schedules") else []
# Backend guard: # Backend guard:
# If any Payment Entry exists, schedule-based PRs are not allowed. # If any Payment Entry exists, schedule-based PRs are not allowed.
@@ -931,7 +931,7 @@ def apply_payment_references(pr, payment_reference):
def set_payment_references(payment_schedules): def set_payment_references(payment_schedules):
payment_schedules = json.loads(payment_schedules) if payment_schedules else [] payment_schedules = frappe.parse_json(payment_schedules) if payment_schedules else []
payment_reference = [] payment_reference = []
for row in payment_schedules: for row in payment_schedules:

View File

@@ -1036,8 +1036,7 @@ def make_sales_return(source_name: str, target_doc: Document | str | None = None
def make_merge_log(invoices: str | list): def make_merge_log(invoices: str | list):
import json import json
if isinstance(invoices, str): invoices = frappe.parse_json(invoices)
invoices = json.loads(invoices)
if len(invoices) == 0: if len(invoices) == 0:
frappe.throw(_("At least one invoice has to be selected.")) frappe.throw(_("At least one invoice has to be selected."))

View File

@@ -341,8 +341,7 @@ def apply_pricing_rule(args: str | dict, doc: str | dict | Document | None = Non
} }
""" """
if isinstance(args, str): args = frappe.parse_json(args)
args = json.loads(args)
args = frappe._dict(args) args = frappe._dict(args)
@@ -397,8 +396,7 @@ def get_pricing_rule_for_item(args, doc=None, for_validate=False):
get_product_discount_rule, get_product_discount_rule,
) )
if isinstance(doc, str): doc = frappe.parse_json(doc)
doc = json.loads(doc)
if doc: if doc:
doc = frappe.get_doc(doc) doc = frappe.get_doc(doc)
@@ -628,9 +626,7 @@ def remove_pricing_rule_for_item(
get_pricing_rule_items, get_pricing_rule_items,
) )
if isinstance(item_details, str): item_details = frappe._dict(frappe.parse_json(item_details))
item_details = json.loads(item_details)
item_details = frappe._dict(item_details)
for d in get_applied_pricing_rules(pricing_rules): for d in get_applied_pricing_rules(pricing_rules):
if not d or not frappe.db.exists("Pricing Rule", d): if not d or not frappe.db.exists("Pricing Rule", d):
@@ -671,8 +667,7 @@ def remove_pricing_rule_for_item(
@frappe.whitelist() @frappe.whitelist()
def remove_pricing_rules(item_list: str | list): def remove_pricing_rules(item_list: str | list):
if isinstance(item_list, str): item_list = frappe.parse_json(item_list)
item_list = json.loads(item_list)
out = [] out = []
for item in item_list: for item in item_list:

View File

@@ -636,7 +636,7 @@ def remove_free_item(doc):
def get_applied_pricing_rules(pricing_rules): def get_applied_pricing_rules(pricing_rules):
if pricing_rules: if pricing_rules:
if pricing_rules.startswith("["): if pricing_rules.startswith("["):
return json.loads(pricing_rules) return frappe.parse_json(pricing_rules)
else: else:
return pricing_rules.split(",") return pricing_rules.split(",")

View File

@@ -542,8 +542,7 @@ def check_multi_currency(pr_doc):
def is_any_doc_running(for_filter: str | dict | None = None) -> str | None: def is_any_doc_running(for_filter: str | dict | None = None) -> str | None:
running_doc = None running_doc = None
if for_filter: if for_filter:
if isinstance(for_filter, str): for_filter = frappe.parse_json(for_filter)
for_filter = json.loads(for_filter)
running_doc = frappe.db.get_value( running_doc = frappe.db.get_value(
"Process Payment Reconciliation", "Process Payment Reconciliation",

View File

@@ -50,8 +50,7 @@ def make_purchase_receipt(
): ):
if args is None: if args is None:
args = {} args = {}
if isinstance(args, str): args = frappe.parse_json(args)
args = json.loads(args)
def post_parent_process(source_parent, target_parent): def post_parent_process(source_parent, target_parent):
remove_items_with_zero_qty(target_parent) remove_items_with_zero_qty(target_parent)

View File

@@ -201,9 +201,9 @@ def get_linked_advances(company, docname):
@frappe.whitelist() @frappe.whitelist()
def create_unreconcile_doc_for_selection(selections: str | None = None): def create_unreconcile_doc_for_selection(selections: str | list | None = None):
if selections: if selections:
selections = json.loads(selections) selections = frappe.parse_json(selections)
# assuming each row is a unique voucher # assuming each row is a unique voucher
for row in selections: for row in selections:
unrecon = frappe.new_doc("Unreconcile Payment") unrecon = frappe.new_doc("Unreconcile Payment")

View File

@@ -30,7 +30,7 @@ class ChildItemUpdater:
self._ordered_items: dict | None = None self._ordered_items: dict | None = None
self._purchased_items: dict | None = None self._purchased_items: dict | None = None
def update(self, trans_items: str) -> None: def update(self, trans_items: str | list) -> None:
"""Process item additions, edits, and deletions from trans_items JSON.""" """Process item additions, edits, and deletions from trans_items JSON."""
from erpnext.buying.doctype.supplier_quotation.supplier_quotation import get_purchased_items from erpnext.buying.doctype.supplier_quotation.supplier_quotation import get_purchased_items
from erpnext.selling.doctype.quotation.mapper import get_ordered_items from erpnext.selling.doctype.quotation.mapper import get_ordered_items

View File

@@ -995,8 +995,7 @@ class Asset(AccountsController):
@frappe.whitelist() @frappe.whitelist()
def get_depreciation_rate(self, args: str | dict | Document, on_validate: bool = False): def get_depreciation_rate(self, args: str | dict | Document, on_validate: bool = False):
if isinstance(args, str): args = frappe.parse_json(args)
args = json.loads(args)
rate_field_precision = frappe.get_single_value("System Settings", "float_precision") or 2 rate_field_precision = frappe.get_single_value("System Settings", "float_precision") or 2

View File

@@ -162,8 +162,7 @@ def make_asset_movement(
assets: list[dict] | str, assets: list[dict] | str,
purpose: str = "Transfer", purpose: str = "Transfer",
): ):
if isinstance(assets, str): assets = frappe.parse_json(assets)
assets = json.loads(assets)
if len(assets) == 0: if len(assets) == 0:
frappe.throw(_("At least one asset has to be selected.")) frappe.throw(_("At least one asset has to be selected."))

View File

@@ -669,8 +669,7 @@ def get_service_item_details(ctx: ItemDetailsCtx) -> frappe._dict:
@frappe.whitelist() @frappe.whitelist()
def get_items_tagged_to_wip_composite_asset(params: dict | str): def get_items_tagged_to_wip_composite_asset(params: dict | str):
if isinstance(params, str): params = frappe.parse_json(params)
params = json.loads(params)
fields = [ fields = [
"item_code", "item_code",

View File

@@ -27,8 +27,7 @@ def make_purchase_receipt(
): ):
if args is None: if args is None:
args = {} args = {}
if isinstance(args, str): args = frappe.parse_json(args)
args = json.loads(args)
has_unit_price_items = frappe.db.get_value("Purchase Order", source_name, "has_unit_price_items") has_unit_price_items = frappe.db.get_value("Purchase Order", source_name, "has_unit_price_items")
@@ -123,8 +122,7 @@ def make_purchase_invoice_from_portal(purchase_order_name: str):
def get_mapped_purchase_invoice(source_name, target_doc=None, ignore_permissions=False, args=None): def get_mapped_purchase_invoice(source_name, target_doc=None, ignore_permissions=False, args=None):
if args is None: if args is None:
args = {} args = {}
if isinstance(args, str): args = frappe.parse_json(args)
args = json.loads(args)
def postprocess(source, target): def postprocess(source, target):
target.flags.ignore_permissions = ignore_permissions target.flags.ignore_permissions = ignore_permissions
@@ -294,7 +292,7 @@ def get_mapped_subcontracting_order(source_name: str, target_doc: str | Document
) or frappe.get_value("Production Plan", target_doc.production_plan, "reserve_stock") ) or frappe.get_value("Production Plan", target_doc.production_plan, "reserve_stock")
if target_doc and isinstance(target_doc, str): if target_doc and isinstance(target_doc, str):
target_doc = json.loads(target_doc) target_doc = frappe.parse_json(target_doc)
for key in ["service_items", "items", "supplied_items"]: for key in ["service_items", "items", "supplied_items"]:
if key in target_doc: if key in target_doc:
del target_doc[key] del target_doc[key]

View File

@@ -549,11 +549,11 @@ def item_last_purchase_rate(name, conversion_rate, item_code, conversion_factor=
@frappe.whitelist() @frappe.whitelist()
def close_or_unclose_purchase_orders(names: str, status: str): def close_or_unclose_purchase_orders(names: str | list, status: str):
if not frappe.has_permission("Purchase Order", "write"): if not frappe.has_permission("Purchase Order", "write"):
frappe.throw(_("Not permitted"), frappe.PermissionError) frappe.throw(_("Not permitted"), frappe.PermissionError)
names = json.loads(names) names = frappe.parse_json(names)
for name in names: for name in names:
po = frappe.get_lazy_doc("Purchase Order", name) po = frappe.get_lazy_doc("Purchase Order", name)
if po.docstatus == 1: if po.docstatus == 1:

View File

@@ -57,8 +57,7 @@ def make_supplier_quotation_from_rfq(
# This method is used to make supplier quotation from supplier's portal. # This method is used to make supplier quotation from supplier's portal.
@frappe.whitelist() @frappe.whitelist()
def create_supplier_quotation(doc: str | Document | dict): def create_supplier_quotation(doc: str | Document | dict):
if isinstance(doc, str): doc = frappe.parse_json(doc)
doc = json.loads(doc)
if frappe.session.user not in frappe.get_all( if frappe.session.user not in frappe.get_all(
"Portal User", {"parent": doc.get("supplier")}, pluck="user" "Portal User", {"parent": doc.get("supplier")}, pluck="user"

View File

@@ -15,8 +15,7 @@ def make_purchase_order(
): ):
if args is None: if args is None:
args = {} args = {}
if isinstance(args, str): args = frappe.parse_json(args)
args = json.loads(args)
def set_missing_values(source, target): def set_missing_values(source, target):
target.run_method("set_missing_values") target.run_method("set_missing_values")

View File

@@ -124,12 +124,12 @@ def check_on_hold_or_closed_status(doctype, docname) -> None:
@frappe.whitelist() @frappe.whitelist()
def get_linked_material_requests(items: str): def get_linked_material_requests(items: str | list):
""" """
Retrieve Material Requests linked to a list of items. Retrieve Material Requests linked to a list of items.
""" """
items = json.loads(items) items = frappe.parse_json(items)
mr_list = [] mr_list = []
mr = frappe.qb.DocType("Material Request") mr = frappe.qb.DocType("Material Request")

View File

@@ -45,8 +45,7 @@ def get_variant(
if item_template.variant_based_on == "Manufacturer" and manufacturer: if item_template.variant_based_on == "Manufacturer" and manufacturer:
return make_variant_based_on_manufacturer(item_template, manufacturer, manufacturer_part_no) return make_variant_based_on_manufacturer(item_template, manufacturer, manufacturer_part_no)
if isinstance(args, str): args = frappe.parse_json(args)
args = json.loads(args)
attribute_args = {k: v for k, v in args.items() if k != "use_template_image"} attribute_args = {k: v for k, v in args.items() if k != "use_template_image"}
if not attribute_args: if not attribute_args:
@@ -258,8 +257,7 @@ def find_variant(template, args, variant_item_code=None):
@frappe.whitelist() @frappe.whitelist()
def create_variant(item: str, args: dict | str, use_template_image: bool = False): def create_variant(item: str, args: dict | str, use_template_image: bool = False):
use_template_image = frappe.parse_json(use_template_image) use_template_image = frappe.parse_json(use_template_image)
if isinstance(args, str): args = frappe.parse_json(args)
args = json.loads(args)
template = frappe.get_doc("Item", item) template = frappe.get_doc("Item", item)
variant = frappe.new_doc("Item") variant = frappe.new_doc("Item")
@@ -286,10 +284,7 @@ def create_variant(item: str, args: dict | str, use_template_image: bool = False
def enqueue_multiple_variant_creation(item: str, args: dict | str, use_template_image: bool = False): def enqueue_multiple_variant_creation(item: str, args: dict | str, use_template_image: bool = False):
use_template_image = frappe.parse_json(use_template_image) use_template_image = frappe.parse_json(use_template_image)
# There can be innumerable attribute combinations, enqueue # There can be innumerable attribute combinations, enqueue
if isinstance(args, str): variants = frappe.parse_json(args)
variants = json.loads(args)
else:
variants = args
variants = {key: values for key, values in variants.items() if values} variants = {key: values for key, values in variants.items() if values}
if not variants: if not variants:
frappe.throw(_("Please select at least one attribute value")) frappe.throw(_("Please select at least one attribute value"))
@@ -315,8 +310,7 @@ def enqueue_multiple_variant_creation(item: str, args: dict | str, use_template_
def create_multiple_variants(item, args, use_template_image=False): def create_multiple_variants(item, args, use_template_image=False):
count = 0 count = 0
if isinstance(args, str): args = frappe.parse_json(args)
args = json.loads(args)
args = {key: values for key, values in args.items() if values} args = {key: values for key, values in args.items() if values}
template_item = frappe.get_doc("Item", item) template_item = frappe.get_doc("Item", item)
@@ -483,7 +477,7 @@ def make_variant_item_code(template_item_code, template_item_name, variant):
@frappe.whitelist() @frappe.whitelist()
def create_variant_doc_for_quick_entry(template: str, args: dict | str): def create_variant_doc_for_quick_entry(template: str, args: dict | str):
variant_based_on = frappe.db.get_value("Item", template, "variant_based_on") variant_based_on = frappe.db.get_value("Item", template, "variant_based_on")
args = json.loads(args) args = frappe.parse_json(args)
if variant_based_on == "Manufacturer": if variant_based_on == "Manufacturer":
variant = get_variant(template, **args) variant = get_variant(template, **args)
else: else:

View File

@@ -213,8 +213,7 @@ def item_query(
""" """
doctype = "Item" doctype = "Item"
if isinstance(filters, str): filters = frappe.parse_json(filters)
filters = json.loads(filters)
if filters and isinstance(filters, dict): if filters and isinstance(filters, dict):
if filters.get("customer") or filters.get("supplier"): if filters.get("customer") or filters.get("supplier"):

View File

@@ -625,8 +625,7 @@ def repost_required_for_queue(doc: StockController) -> bool:
def check_item_quality_inspection(doctype: str, docstatus: str | int, items: str | list[dict]): def check_item_quality_inspection(doctype: str, docstatus: str | int, items: str | list[dict]):
from erpnext.stock.services.quality_inspection_service import INSPECTION_FIELDNAME_MAP from erpnext.stock.services.quality_inspection_service import INSPECTION_FIELDNAME_MAP
if isinstance(items, str): items = frappe.parse_json(items)
items = json.loads(items)
inspection_fieldname = INSPECTION_FIELDNAME_MAP.get(doctype) inspection_fieldname = INSPECTION_FIELDNAME_MAP.get(doctype)
if inspection_fieldname is None: if inspection_fieldname is None:
@@ -658,8 +657,7 @@ def check_item_quality_inspection(doctype: str, docstatus: str | int, items: str
def make_quality_inspections( def make_quality_inspections(
company: str, doctype: str, docname: str, items: str | list, inspection_type: str company: str, doctype: str, docname: str, items: str | list, inspection_type: str
): ):
if isinstance(items, str): items = frappe.parse_json(items)
items = json.loads(items)
inspections = [] inspections = []
for item in items: for item in items:

View File

@@ -342,7 +342,7 @@ class calculate_taxes_and_totals:
self._set_in_company_currency(item, ["net_rate", "net_amount"]) self._set_in_company_currency(item, ["net_rate", "net_amount"])
def _load_item_tax_rate(self, item_tax_rate): def _load_item_tax_rate(self, item_tax_rate):
return json.loads(item_tax_rate) if item_tax_rate else {} return frappe.parse_json(item_tax_rate) if item_tax_rate else {}
def get_current_tax_fraction(self, tax, item_tax_map): def get_current_tax_fraction(self, tax, item_tax_map):
""" """

View File

@@ -35,8 +35,7 @@ class ContractTemplate(Document):
@frappe.whitelist() @frappe.whitelist()
def get_contract_template(template_name: str, doc: str | dict | Document): def get_contract_template(template_name: str, doc: str | dict | Document):
if isinstance(doc, str): doc = frappe.parse_json(doc)
doc = json.loads(doc)
contract_template = frappe.get_doc("Contract Template", template_name) contract_template = frappe.get_doc("Contract Template", template_name)
contract_terms = None contract_terms = None

View File

@@ -391,7 +391,7 @@ def get_item_details(item_code: str):
@frappe.whitelist() @frappe.whitelist()
def set_multiple_status(names: str | list[str], status: str): def set_multiple_status(names: str | list[str], status: str):
names = json.loads(names) names = frappe.parse_json(names)
for name in names: for name in names:
opp = frappe.get_doc("Opportunity", name) opp = frappe.get_doc("Opportunity", name)
opp.status = status opp.status = status

View File

@@ -33,7 +33,7 @@ def create_prospect_against_crm_deal():
pass pass
if doc.contacts and len(doc.contacts): if doc.contacts and len(doc.contacts):
create_contacts(json.loads(doc.contacts), prospect.company_name, "Prospect", prospect_name) create_contacts(frappe.parse_json(doc.contacts), prospect.company_name, "Prospect", prospect_name)
create_address("Prospect", prospect_name, doc.address) create_address("Prospect", prospect_name, doc.address)
frappe.response["message"] = prospect_name frappe.response["message"] = prospect_name
@@ -69,8 +69,7 @@ def create_contacts(contacts, organization=None, link_doctype=None, link_docname
def create_address(doctype, docname, address): def create_address(doctype, docname, address):
if not address: if not address:
return return
if isinstance(address, str): address = frappe.parse_json(address)
address = json.loads(address)
try: try:
_address = frappe.db.exists("Address", address.get("name")) _address = frappe.db.exists("Address", address.get("name"))
if not _address: if not _address:
@@ -153,7 +152,7 @@ def create_customer(customer_data: dict | None = None):
customer.insert(ignore_permissions=True) customer.insert(ignore_permissions=True)
customer_name = customer.name customer_name = customer.name
contacts = json.loads(customer_data.get("contacts")) contacts = frappe.parse_json(customer_data.get("contacts"))
create_contacts(contacts, customer_name, "Customer", customer_name) create_contacts(contacts, customer_name, "Customer", customer_name)
create_address("Customer", customer_name, customer_data.get("address")) create_address("Customer", customer_name, customer_data.get("address"))
return customer_name return customer_name

View File

@@ -156,13 +156,15 @@ def process_genericode_import(
code_column: str, code_column: str,
title_column: str | None = None, title_column: str | None = None,
description_column: str | None = None, description_column: str | None = None,
filters: str | None = None, filters: str | dict | None = None,
): ):
from erpnext.edi.doctype.common_code.common_code import import_genericode from erpnext.edi.doctype.common_code.common_code import import_genericode
column_map = {"code": code_column, "title": title_column, "description": description_column} column_map = {"code": code_column, "title": title_column, "description": description_column}
return import_genericode(code_list_name, file_name, column_map, json.loads(filters) if filters else None) return import_genericode(
code_list_name, file_name, column_map, frappe.parse_json(filters) if filters else None
)
def get_genericode_columns_and_examples(root): def get_genericode_columns_and_examples(root):

View File

@@ -51,8 +51,8 @@ def get_plaid_configuration():
@frappe.whitelist() @frappe.whitelist()
def add_institution(token: str, response: str): def add_institution(token: str, response: str | dict):
response = json.loads(response) response = frappe.parse_json(response)
plaid = PlaidConnector() plaid = PlaidConnector()
access_token = plaid.get_access_token(token) access_token = plaid.get_access_token(token)
@@ -80,13 +80,8 @@ def add_institution(token: str, response: str):
@frappe.whitelist() @frappe.whitelist()
def add_bank_accounts(response: str | dict, bank: str | dict, company: str): def add_bank_accounts(response: str | dict, bank: str | dict, company: str):
try: response = frappe.parse_json(response)
response = json.loads(response) bank = frappe.parse_json(bank)
except TypeError:
pass
if isinstance(bank, str):
bank = json.loads(bank)
result = [] result = []
parent_gl_account = frappe.db.get_all( parent_gl_account = frappe.db.get_all(
@@ -358,8 +353,8 @@ def get_company(bank_account_name):
@frappe.whitelist() @frappe.whitelist()
def update_bank_account_ids(response: str): def update_bank_account_ids(response: str | dict):
data = json.loads(response) data = frappe.parse_json(response)
institution_name = data["institution"]["name"] institution_name = data["institution"]["name"]
bank = frappe.get_doc("Bank", institution_name).as_dict() bank = frappe.get_doc("Bank", institution_name).as_dict()
bank_account_name = f"{data['account']['name']} - {institution_name}" bank_account_name = f"{data['account']['name']} - {institution_name}"

View File

@@ -712,6 +712,10 @@ default_log_clearing_doctypes = {
export_python_type_annotations = True export_python_type_annotations = True
# Send non-GET requests for ERPNext's endpoints as native `application/json`
# bodies instead of form-encoded, per-key JSON-stringified values.
use_json_request_body = True
fields_for_group_similar_items = ["qty", "amount"] fields_for_group_similar_items = ["qty", "amount"]
# Translation # Translation

View File

@@ -585,7 +585,7 @@ class BOM(WebsiteGenerator):
if isinstance(kwargs, str): if isinstance(kwargs, str):
import json import json
kwargs = json.loads(kwargs) kwargs = frappe.parse_json(kwargs)
return kwargs return kwargs

View File

@@ -32,8 +32,7 @@ class BOMUpdateTool(Document):
def enqueue_replace_bom(boms: dict | str | None = None, args: dict | str | None = None) -> "BOMUpdateLog": def enqueue_replace_bom(boms: dict | str | None = None, args: dict | str | None = None) -> "BOMUpdateLog":
"""Returns a BOM Update Log (that queues a job) for BOM Replacement.""" """Returns a BOM Update Log (that queues a job) for BOM Replacement."""
boms = boms or args boms = boms or args
if isinstance(boms, str): boms = frappe.parse_json(boms)
boms = json.loads(boms)
update_log = create_bom_update_log(boms=boms) update_log = create_bom_update_log(boms=boms)
return update_log return update_log

View File

@@ -1685,8 +1685,7 @@ class JobCard(Document):
@frappe.whitelist() @frappe.whitelist()
def make_time_log(kwargs: str | dict): def make_time_log(kwargs: str | dict):
if isinstance(kwargs, str): kwargs = frappe.parse_json(kwargs)
kwargs = json.loads(kwargs)
kwargs = frappe._dict(kwargs) kwargs = frappe._dict(kwargs)
doc = frappe.get_doc("Job Card", kwargs.job_card_id) doc = frappe.get_doc("Job Card", kwargs.job_card_id)
@@ -1761,8 +1760,7 @@ def get_job_card_filter_conditions(jc, filters):
Replaces the previous raw SQL ``get_filters_cond`` based filtering so that all Replaces the previous raw SQL ``get_filters_cond`` based filtering so that all
user supplied values are passed as bound parameters via the query builder. user supplied values are passed as bound parameters via the query builder.
""" """
if isinstance(filters, str): filters = frappe.parse_json(filters)
filters = json.loads(filters)
if not filters: if not filters:
return [] return []

View File

@@ -159,8 +159,7 @@ def get_items_for_material_requests(
def _normalize_mr_doc(doc): def _normalize_mr_doc(doc):
if isinstance(doc, str): doc = frappe._dict(frappe.parse_json(doc))
doc = frappe._dict(json.loads(doc))
return doc return doc

View File

@@ -24,8 +24,7 @@ def get_bin_details(
): ):
frappe.has_permission("Production Plan", "read", throw=True) frappe.has_permission("Production Plan", "read", throw=True)
if isinstance(row, str): row = frappe._dict(frappe.parse_json(row))
row = frappe._dict(json.loads(row))
bin = frappe.qb.DocType("Bin") bin = frappe.qb.DocType("Bin")
subquery = _bin_warehouse_subquery(bin, company, row, for_warehouse, all_warehouse) subquery = _bin_warehouse_subquery(bin, company, row, for_warehouse, all_warehouse)
@@ -65,8 +64,7 @@ def _bin_qty_columns(bin):
def get_warehouse_list(warehouses): def get_warehouse_list(warehouses):
warehouse_list = [] warehouse_list = []
if isinstance(warehouses, str): warehouses = frappe.parse_json(warehouses)
warehouses = json.loads(warehouses)
for row in warehouses: for row in warehouses:
child_warehouses = frappe.db.get_descendants("Warehouse", row.get("warehouse")) child_warehouses = frappe.db.get_descendants("Warehouse", row.get("warehouse"))

View File

@@ -148,8 +148,7 @@ def _new_work_order(item, bom_no, company, item_details, use_multi_level_bom):
def add_variant_item(variant_items, wo_doc, bom_no, table_name="items"): def add_variant_item(variant_items, wo_doc, bom_no, table_name="items"):
if isinstance(variant_items, str): variant_items = frappe.parse_json(variant_items)
variant_items = json.loads(variant_items)
for item in variant_items: for item in variant_items:
_add_variant_row(item, wo_doc, bom_no, table_name) _add_variant_row(item, wo_doc, bom_no, table_name)
@@ -289,8 +288,7 @@ def _set_stock_entry_warehouses(stock_entry, work_order, purpose, target_warehou
def make_job_card(work_order: str, operations: str | list, parent_bom: str | None = None): def make_job_card(work_order: str, operations: str | list, parent_bom: str | None = None):
frappe.has_permission("Job Card", "create", throw=True) frappe.has_permission("Job Card", "create", throw=True)
if isinstance(operations, str): operations = frappe.parse_json(operations)
operations = json.loads(operations)
work_order = frappe.get_doc("Work Order", work_order) work_order = frappe.get_doc("Work Order", work_order)
for row in operations: for row in operations:
@@ -469,10 +467,10 @@ def get_work_order_operation_data(work_order, operation, workstation):
@frappe.whitelist() @frappe.whitelist()
def create_pick_list(source_name: str, target_doc: str | None = None, for_qty: float | None = None): def create_pick_list(source_name: str, target_doc: str | dict | None = None, for_qty: float | None = None):
frappe.has_permission("Pick List", "create", throw=True) frappe.has_permission("Pick List", "create", throw=True)
for_qty = for_qty or json.loads(target_doc).get("for_qty") for_qty = for_qty or frappe.parse_json(target_doc).get("for_qty")
max_finished_goods_qty = frappe.db.get_value("Work Order", source_name, "qty") max_finished_goods_qty = frappe.db.get_value("Work Order", source_name, "qty")
postprocess = partial( postprocess = partial(
_set_pick_list_item_qty, for_qty=for_qty, max_finished_goods_qty=max_finished_goods_qty _set_pick_list_item_qty, for_qty=for_qty, max_finished_goods_qty=max_finished_goods_qty

View File

@@ -629,11 +629,11 @@ def allow_to_make_project_update(project, time, frequency):
@frappe.whitelist() @frappe.whitelist()
def create_duplicate_project(prev_doc: str, project_name: str): def create_duplicate_project(prev_doc: str | dict, project_name: str):
"""Create duplicate project based on the old project""" """Create duplicate project based on the old project"""
import json import json
prev_doc = json.loads(prev_doc) prev_doc = frappe.parse_json(prev_doc)
if project_name == prev_doc.get("name"): if project_name == prev_doc.get("name"):
frappe.throw(_("Use a name that is different from previous project name")) frappe.throw(_("Use a name that is different from previous project name"))

View File

@@ -363,8 +363,8 @@ def get_project(doctype: str, txt: str, searchfield: str, start: int, page_len:
@frappe.whitelist() @frappe.whitelist()
def set_multiple_status(names: str, status: str): def set_multiple_status(names: str | list, status: str):
names = json.loads(names) names = frappe.parse_json(names)
for name in names: for name in names:
task = frappe.get_doc("Task", name) task = frappe.get_doc("Task", name)
task.status = status task.status = status
@@ -459,8 +459,8 @@ def add_node():
@frappe.whitelist() @frappe.whitelist()
def add_multiple_tasks(data: str, parent: str): def add_multiple_tasks(data: str | list, parent: str):
data = json.loads(data) data = frappe.parse_json(data)
new_doc = {"doctype": "Task", "parent_task": parent if parent != "All Tasks" else ""} new_doc = {"doctype": "Task", "parent_task": parent if parent != "All Tasks" else ""}
new_doc["project"] = frappe.db.get_value("Task", {"name": parent}, "project") or "" new_doc["project"] = frappe.db.get_value("Task", {"name": parent}, "project") or ""

View File

@@ -497,7 +497,7 @@ def get_activity_cost(
@frappe.whitelist() @frappe.whitelist()
def get_events(start: str, end: str, filters: str | None = None): def get_events(start: str, end: str, filters: str | list | dict | None = None):
"""Returns events for Gantt / Calendar view rendering. """Returns events for Gantt / Calendar view rendering.
:param start: Start date-time. :param start: Start date-time.
:param end: End date-time. :param end: End date-time.
@@ -505,7 +505,7 @@ def get_events(start: str, end: str, filters: str | None = None):
""" """
from erpnext.utilities.query import get_event_conditions_qb from erpnext.utilities.query import get_event_conditions_qb
filters = json.loads(filters) if filters else {} filters = frappe.parse_json(filters) if filters else {}
tsd = frappe.qb.DocType("Timesheet Detail") tsd = frappe.qb.DocType("Timesheet Detail")
ts = frappe.qb.DocType("Timesheet") ts = frappe.qb.DocType("Timesheet")

View File

@@ -104,7 +104,7 @@ def prepare_invoice(invoice, progressive_number):
def get_conditions(filters): def get_conditions(filters):
filters = json.loads(filters) filters = frappe.parse_json(filters)
conditions = {"docstatus": 1, "company_tax_id": ("!=", "")} conditions = {"docstatus": 1, "company_tax_id": ("!=", "")}

View File

@@ -84,7 +84,7 @@ def get_columns():
@frappe.whitelist() @frappe.whitelist()
def irs_1099_print(filters: str): def irs_1099_print(filters: str | dict):
if not filters: if not filters:
frappe._dict( frappe._dict(
{ {
@@ -93,7 +93,7 @@ def irs_1099_print(filters: str):
} }
) )
else: else:
filters = frappe._dict(json.loads(filters)) filters = frappe._dict(frappe.parse_json(filters))
fiscal_year_doc = get_fiscal_year(fiscal_year=filters.fiscal_year, as_dict=True) fiscal_year_doc = get_fiscal_year(fiscal_year=filters.fiscal_year, as_dict=True)
fiscal_year = cstr(fiscal_year_doc.year_start_date.year) fiscal_year = cstr(fiscal_year_doc.year_start_date.year)

View File

@@ -559,8 +559,7 @@ def check_credit_limit(customer, company, ignore_outstanding_sales_order=False,
def send_emails( def send_emails(
customer: str, customer_outstanding: float, credit_limit: float, credit_controller_users_list: str | list customer: str, customer_outstanding: float, credit_limit: float, credit_controller_users_list: str | list
): ):
if isinstance(credit_controller_users_list, str): credit_controller_users_list = frappe.parse_json(credit_controller_users_list)
credit_controller_users_list = json.loads(credit_controller_users_list)
subject = _("Credit limit reached for customer {0}").format(customer) subject = _("Credit limit reached for customer {0}").format(customer)
message = _("Credit limit has been crossed for customer {0} ({1}/{2})").format( message = _("Credit limit has been crossed for customer {0} ({1}/{2})").format(
customer, customer_outstanding, credit_limit customer, customer_outstanding, credit_limit

View File

@@ -31,8 +31,7 @@ def make_sales_order(
def _make_sales_order(source_name, target_doc=None, ignore_permissions=False, args=None): def _make_sales_order(source_name, target_doc=None, ignore_permissions=False, args=None):
if args is None: if args is None:
args = {} args = {}
if isinstance(args, str): args = frappe.parse_json(args)
args = json.loads(args)
customer = _make_customer(source_name, ignore_permissions) customer = _make_customer(source_name, ignore_permissions)
ordered_items = get_ordered_items(source_name) ordered_items = get_ordered_items(source_name)
@@ -151,8 +150,7 @@ def make_sales_invoice(
def _make_sales_invoice(source_name, target_doc=None, ignore_permissions=False, args=None): def _make_sales_invoice(source_name, target_doc=None, ignore_permissions=False, args=None):
if args is None: if args is None:
args = {} args = {}
if isinstance(args, str): args = frappe.parse_json(args)
args = json.loads(args)
customer = _make_customer(source_name, ignore_permissions) customer = _make_customer(source_name, ignore_permissions)

View File

@@ -430,8 +430,7 @@ def make_sales_invoice(
): ):
if args is None: if args is None:
args = {} args = {}
if isinstance(args, str): args = frappe.parse_json(args)
args = json.loads(args)
# 0 qty is accepted, as the qty is uncertain for some items # 0 qty is accepted, as the qty is uncertain for some items
has_unit_price_items = frappe.db.get_value("Sales Order", source_name, "has_unit_price_items") has_unit_price_items = frappe.db.get_value("Sales Order", source_name, "has_unit_price_items")
@@ -675,8 +674,7 @@ def make_purchase_order(
if not selected_items: if not selected_items:
return return
if isinstance(selected_items, str): selected_items = frappe.parse_json(selected_items)
selected_items = json.loads(selected_items)
def set_missing_values(source, target): def set_missing_values(source, target):
target.supplier = supplier target.supplier = supplier
@@ -843,9 +841,9 @@ def set_delivery_date(items: list, sales_order: str) -> None:
@frappe.whitelist() @frappe.whitelist()
def make_work_orders(items: str, sales_order: str, company: str, project: str | None = None): def make_work_orders(items: str | dict, sales_order: str, company: str, project: str | None = None):
"""Make Work Orders against the given Sales Order for the given `items`""" """Make Work Orders against the given Sales Order for the given `items`"""
items = json.loads(items).get("items") items = frappe.parse_json(items).get("items")
out = [] out = []
for i in items: for i in items:
@@ -912,8 +910,7 @@ def make_raw_material_request(
if not frappe.has_permission("Sales Order", "write"): if not frappe.has_permission("Sales Order", "write"):
frappe.throw(_("Not permitted"), frappe.PermissionError) frappe.throw(_("Not permitted"), frappe.PermissionError)
if isinstance(items, str): items = frappe._dict(frappe.parse_json(items))
items = frappe._dict(json.loads(items))
for item in items.get("items"): for item in items.get("items"):
item["include_exploded_items"] = items.get("include_exploded_items") item["include_exploded_items"] = items.get("include_exploded_items")
@@ -1089,7 +1086,7 @@ def get_mapped_subcontracting_inward_order(
target_doc.populate_items_table() target_doc.populate_items_table()
if target_doc and isinstance(target_doc, str): if target_doc and isinstance(target_doc, str):
target_doc = json.loads(target_doc) target_doc = frappe.parse_json(target_doc)
for key in ["service_items", "items", "received_items"]: for key in ["service_items", "items", "received_items"]:
if key in target_doc: if key in target_doc:
del target_doc[key] del target_doc[key]

View File

@@ -711,11 +711,11 @@ def is_enable_cutoff_date_on_bulk_delivery_note_creation():
@frappe.whitelist() @frappe.whitelist()
def close_or_unclose_sales_orders(names: str, status: str): def close_or_unclose_sales_orders(names: str | list, status: str):
if not frappe.has_permission("Sales Order", "write"): if not frappe.has_permission("Sales Order", "write"):
frappe.throw(_("Not permitted"), frappe.PermissionError) frappe.throw(_("Not permitted"), frappe.PermissionError)
names = json.loads(names) names = frappe.parse_json(names)
for name in names: for name in names:
so = frappe.get_lazy_doc("Sales Order", name) so = frappe.get_lazy_doc("Sales Order", name)
if so.docstatus == 1: if so.docstatus == 1:

View File

@@ -347,8 +347,8 @@ def check_opening_entry(user: str):
@frappe.whitelist() @frappe.whitelist()
def create_opening_voucher(pos_profile: str, company: str, balance_details: str): def create_opening_voucher(pos_profile: str, company: str, balance_details: str | list):
balance_details = json.loads(balance_details) balance_details = frappe.parse_json(balance_details)
new_pos_opening = frappe.get_doc( new_pos_opening = frappe.get_doc(
{ {

View File

@@ -77,8 +77,7 @@ def get_children(
is_root: bool = False, is_root: bool = False,
include_disabled: str | dict | None = None, include_disabled: str | dict | None = None,
): ):
if isinstance(include_disabled, str): include_disabled = frappe.parse_json(include_disabled)
include_disabled = json.loads(include_disabled)
fields = ["name as value", "is_group as expandable"] fields = ["name as value", "is_group as expandable"]
filters = {} filters = {}

View File

@@ -176,7 +176,7 @@ def get_events(start: DateTimeLikeObject, end: DateTimeLikeObject, filters: str
:param filters: Filters (JSON). :param filters: Filters (JSON).
""" """
if filters: if filters:
filters = json.loads(filters) filters = frappe.parse_json(filters)
else: else:
filters = [] filters = []

View File

@@ -37,8 +37,7 @@ class TermsandConditions(Document):
@frappe.whitelist() @frappe.whitelist()
def get_terms_and_conditions(template_name: str, doc: str | dict): def get_terms_and_conditions(template_name: str, doc: str | dict):
if isinstance(doc, str): doc = frappe.parse_json(doc)
doc = json.loads(doc)
terms_and_conditions = frappe.get_doc("Terms and Conditions", template_name) terms_and_conditions = frappe.get_doc("Terms and Conditions", template_name)

View File

@@ -404,8 +404,7 @@ def make_batch(kwargs):
def get_pos_reserved_batch_qty(filters: dict | str): def get_pos_reserved_batch_qty(filters: dict | str):
import json import json
if isinstance(filters, str): filters = frappe.parse_json(filters)
filters = json.loads(filters)
p = frappe.qb.DocType("POS Invoice").as_("p") p = frappe.qb.DocType("POS Invoice").as_("p")
item = frappe.qb.DocType("POS Invoice Item").as_("item") item = frappe.qb.DocType("POS Invoice Item").as_("item")

View File

@@ -66,8 +66,7 @@ def make_sales_invoice(
if args is None: if args is None:
args = {} args = {}
if isinstance(args, str): args = frappe.parse_json(args)
args = json.loads(args)
doc = frappe.get_doc("Delivery Note", source_name) doc = frappe.get_doc("Delivery Note", source_name)

View File

@@ -53,8 +53,7 @@ def make_purchase_order(
): ):
if args is None: if args is None:
args = {} args = {}
if isinstance(args, str): args = frappe.parse_json(args)
args = json.loads(args)
is_subcontracted = ( is_subcontracted = (
frappe.db.get_value("Material Request", source_name, "material_request_type") == "Subcontracting" frappe.db.get_value("Material Request", source_name, "material_request_type") == "Subcontracting"

View File

@@ -432,7 +432,7 @@ def on_doctype_update():
@frappe.whitelist() @frappe.whitelist()
def get_items_from_product_bundle(row: str): def get_items_from_product_bundle(row: str | dict):
"""Item details for each component of a Product Bundle. """Item details for each component of a Product Bundle.
``row.product_bundle`` selects a specific version by document name (the buying ``row.product_bundle`` selects a specific version by document name (the buying
@@ -441,7 +441,7 @@ def get_items_from_product_bundle(row: str):
""" """
from erpnext.selling.doctype.product_bundle.product_bundle import get_active_product_bundle from erpnext.selling.doctype.product_bundle.product_bundle import get_active_product_bundle
row, items = ItemDetailsCtx(json.loads(row)), [] row, items = ItemDetailsCtx(frappe.parse_json(row)), []
if bundle_name := row.get("product_bundle"): if bundle_name := row.get("product_bundle"):
frappe.has_permission("Product Bundle", "read", bundle_name, throw=True) frappe.has_permission("Product Bundle", "read", bundle_name, throw=True)

View File

@@ -113,8 +113,7 @@ def create_dn_for_pick_lists(
"""Get Items from Multiple Pick Lists and create a Delivery Note for filtered customer""" """Get Items from Multiple Pick Lists and create a Delivery Note for filtered customer"""
if kwargs is None: if kwargs is None:
kwargs = {} kwargs = {}
if isinstance(kwargs, str): kwargs = frappe.parse_json(kwargs)
kwargs = json.loads(kwargs)
pick_list = frappe.get_doc("Pick List", source_name) pick_list = frappe.get_doc("Pick List", source_name)
validate_item_locations(pick_list) validate_item_locations(pick_list)
@@ -282,8 +281,8 @@ def add_product_bundles_to_target(pick_list, target_doc, item_mapper, sales_orde
@frappe.whitelist() @frappe.whitelist()
def create_stock_entry(pick_list: str): def create_stock_entry(pick_list: str | dict):
pick_list = frappe.get_doc(json.loads(pick_list)) pick_list = frappe.get_doc(frappe.parse_json(pick_list))
validate_item_locations(pick_list) validate_item_locations(pick_list)
if stock_entry_exists(pick_list.get("name")): if stock_entry_exists(pick_list.get("name")):

View File

@@ -60,8 +60,7 @@ def make_purchase_invoice(
): ):
if args is None: if args is None:
args = {} args = {}
if isinstance(args, str): args = frappe.parse_json(args)
args = json.loads(args)
from erpnext.accounts.party import get_payment_terms_template from erpnext.accounts.party import get_payment_terms_template

View File

@@ -111,8 +111,7 @@ def apply_putaway_rule(
purpose: Purpose of Stock Entry purpose: Purpose of Stock Entry
sync (optional): Sync with client side only for client side calls sync (optional): Sync with client side only for client side calls
""" """
if isinstance(items, str): items = frappe.parse_json(items)
items = json.loads(items)
items_not_accomodated, updated_table = [], [] items_not_accomodated, updated_table = [], []
item_wise_rules = defaultdict(list) item_wise_rules = defaultdict(list)
@@ -198,7 +197,7 @@ def apply_putaway_rule(
frappe.msgprint(_("Applied putaway rules."), alert=True) frappe.msgprint(_("Applied putaway rules."), alert=True)
return updated_table return updated_table
if sync and json.loads(sync): # sync with client side if sync and frappe.parse_json(sync): # sync with client side
return items return items

View File

@@ -364,8 +364,8 @@ class RepostItemValuation(Document):
@frappe.whitelist() @frappe.whitelist()
def bulk_restart_reposting(names: str): def bulk_restart_reposting(names: str | list):
names = json.loads(names) names = frappe.parse_json(names)
for name in names: for name in names:
doc = frappe.get_doc("Repost Item Valuation", name) doc = frappe.get_doc("Repost Item Valuation", name)
if doc.status != "Failed": if doc.status != "Failed":

View File

@@ -222,8 +222,7 @@ def auto_fetch_serial_number(
@frappe.whitelist() @frappe.whitelist()
def get_pos_reserved_serial_nos(filters: str | dict): def get_pos_reserved_serial_nos(filters: str | dict):
if isinstance(filters, str): filters = frappe.parse_json(filters)
filters = json.loads(filters)
POSInvoice = frappe.qb.DocType("POS Invoice") POSInvoice = frappe.qb.DocType("POS Invoice")
POSInvoiceItem = frappe.qb.DocType("POS Invoice Item") POSInvoiceItem = frappe.qb.DocType("POS Invoice Item")

View File

@@ -1040,8 +1040,7 @@ def ceil_qty_if_uom_has_whole_number(qty, stock_uom):
@frappe.whitelist() @frappe.whitelist()
def move_sample_to_retention_warehouse(company: str, items: str | list): def move_sample_to_retention_warehouse(company: str, items: str | list):
if isinstance(items, str): items = frappe.parse_json(items)
items = json.loads(items)
retention_warehouse = frappe.get_single_value("Stock Settings", "sample_retention_warehouse") retention_warehouse = frappe.get_single_value("Stock Settings", "sample_retention_warehouse")
stock_entry = frappe.new_doc("Stock Entry") stock_entry = frappe.new_doc("Stock Entry")

View File

@@ -253,8 +253,7 @@ def get_supplied_items(
def get_items_from_subcontract_order(source_name: str, target_doc: str | Document | None = None): def get_items_from_subcontract_order(source_name: str, target_doc: str | Document | None = None):
from erpnext.controllers.subcontracting_controller import make_rm_stock_entry from erpnext.controllers.subcontracting_controller import make_rm_stock_entry
if isinstance(target_doc, str): target_doc = frappe.get_doc(frappe.parse_json(target_doc))
target_doc = frappe.get_doc(json.loads(target_doc))
order_doctype = "Purchase Order" if target_doc.purchase_order else "Subcontracting Order" order_doctype = "Purchase Order" if target_doc.purchase_order else "Subcontracting Order"
target_doc = make_rm_stock_entry( target_doc = make_rm_stock_entry(

View File

@@ -1683,8 +1683,7 @@ def get_uom_details(item_code: str, uom: str, qty: float | None):
@frappe.whitelist() @frappe.whitelist()
def get_warehouse_details(args: str | dict): def get_warehouse_details(args: str | dict):
if isinstance(args, str): args = frappe.parse_json(args)
args = json.loads(args)
args = frappe._dict(args) args = frappe._dict(args)

View File

@@ -1239,8 +1239,7 @@ def get_stock_balance_for(
item_dict = frappe.get_cached_value("Item", item_code, ["has_serial_no", "has_batch_no"], as_dict=1) item_dict = frappe.get_cached_value("Item", item_code, ["has_serial_no", "has_batch_no"], as_dict=1)
if isinstance(row, str): row = frappe.parse_json(row)
row = json.loads(row)
if isinstance(row, dict): if isinstance(row, dict):
row = frappe._dict(row) row = frappe._dict(row)

View File

@@ -176,8 +176,7 @@ def get_children(
if is_root: if is_root:
parent = "" parent = ""
if isinstance(include_disabled, str): include_disabled = frappe.parse_json(include_disabled)
include_disabled = json.loads(include_disabled)
fields = ["name as value", "is_group as expandable"] fields = ["name as value", "is_group as expandable"]

View File

@@ -90,8 +90,7 @@ def get_item_details(
item = frappe.get_cached_doc("Item", ctx.item_code) item = frappe.get_cached_doc("Item", ctx.item_code)
validate_item_details(ctx, item) validate_item_details(ctx, item)
if isinstance(doc, str): doc = frappe.parse_json(doc)
doc = json.loads(doc)
if doc: if doc:
ctx.transaction_date = doc.get("transaction_date") or doc.get("posting_date") ctx.transaction_date = doc.get("transaction_date") or doc.get("posting_date")

View File

@@ -100,12 +100,12 @@ def get_data(filters=None):
@frappe.whitelist() @frappe.whitelist()
def update_batch_qty(selected_batches: str | None = None): def update_batch_qty(selected_batches: str | list | None = None):
frappe.has_permission("Batch", "write", throw=True, ignore_share_permissions=True) frappe.has_permission("Batch", "write", throw=True, ignore_share_permissions=True)
if not selected_batches: if not selected_batches:
return return
selected_batches = json.loads(selected_batches) selected_batches = frappe.parse_json(selected_batches)
for row in selected_batches: for row in selected_batches:
batch_name = row.get("batch") batch_name = row.get("batch")

View File

@@ -245,8 +245,7 @@ def get_incoming_rate(args: dict | str, raise_error_if_no_rate: bool = True, fal
"""Get Incoming Rate based on valuation method""" """Get Incoming Rate based on valuation method"""
from erpnext.stock.stock_ledger import get_previous_sle, get_valuation_rate from erpnext.stock.stock_ledger import get_previous_sle, get_valuation_rate
if isinstance(args, str): args = frappe.parse_json(args)
args = json.loads(args)
if not args.get("posting_datetime") and args.get("posting_date"): if not args.get("posting_datetime") and args.get("posting_date"):
args["posting_datetime"] = get_combine_datetime(args.get("posting_date"), args.get("posting_time")) args["posting_datetime"] = get_combine_datetime(args.get("posting_date"), args.get("posting_time"))

View File

@@ -217,8 +217,8 @@ def get_issue_list(doctype, txt, filters, limit_start, limit_page_length=20, ord
@frappe.whitelist() @frappe.whitelist()
def set_multiple_status(names: str, status: str): def set_multiple_status(names: str | list, status: str):
for name in json.loads(names): for name in frappe.parse_json(names):
set_status(name, status) set_status(name, status)

View File

@@ -13,13 +13,9 @@ def transaction_processing(
frappe.has_permission(from_doctype, "read", throw=True) frappe.has_permission(from_doctype, "read", throw=True)
frappe.has_permission(to_doctype, "create", throw=True) frappe.has_permission(to_doctype, "create", throw=True)
if isinstance(data, str): deserialized_data = frappe.parse_json(data)
deserialized_data = json.loads(data)
else:
deserialized_data = data
if isinstance(args, str): args = frappe._dict(frappe.parse_json(args))
args = frappe._dict(json.loads(args))
skipped_records = [d for d in deserialized_data if d.get("status") in ("On Hold", "Closed")] skipped_records = [d for d in deserialized_data if d.get("status") in ("On Hold", "Closed")]

View File

@@ -62,8 +62,7 @@ def get_filter_conditions_qb(doctype, filters, ignore_permissions=None):
if isinstance(filters, Criterion): if isinstance(filters, Criterion):
return [filters] return [filters]
if isinstance(filters, str): filters = frappe.parse_json(filters)
filters = json.loads(filters)
if isinstance(filters, dict): if isinstance(filters, dict):
# Mirror get_filters_cond's dict normalization: a string value prefixed with "!" means # Mirror get_filters_cond's dict normalization: a string value prefixed with "!" means

View File

@@ -101,7 +101,7 @@ def get_available_slots_between(query_start_time, query_end_time, settings):
@frappe.whitelist(allow_guest=True) @frappe.whitelist(allow_guest=True)
def create_appointment(date: str, time: str, tz: str, contact: str): def create_appointment(date: str, time: str, tz: str, contact: str | dict):
handle_appointment_booking_disabled() handle_appointment_booking_disabled()
format_string = "%Y-%m-%d %H:%M:%S" format_string = "%Y-%m-%d %H:%M:%S"
scheduled_time = datetime.datetime.strptime(date + " " + time, format_string) scheduled_time = datetime.datetime.strptime(date + " " + time, format_string)
@@ -112,7 +112,7 @@ def create_appointment(date: str, time: str, tz: str, contact: str):
# Create a appointment document from form # Create a appointment document from form
appointment = frappe.new_doc("Appointment") appointment = frappe.new_doc("Appointment")
appointment.scheduled_time = scheduled_time appointment.scheduled_time = scheduled_time
contact = json.loads(contact) contact = frappe.parse_json(contact)
appointment.customer_name = contact.get("name", None) appointment.customer_name = contact.get("name", None)
appointment.customer_phone_number = contact.get("number", None) appointment.customer_phone_number = contact.get("number", None)
appointment.customer_skype = contact.get("skype", None) appointment.customer_skype = contact.get("skype", None)