From 13995a64b8b9dd891e86a8fd1360db94d9df06e4 Mon Sep 17 00:00:00 2001 From: Nishka Gosalia Date: Fri, 20 Feb 2026 16:37:50 +0530 Subject: [PATCH] refactor(stock): adding type hint for stock module --- erpnext/stock/dashboard/item_dashboard.py | 7 ++- .../dashboard/warehouse_capacity_dashboard.py | 14 +++--- .../stock_value_by_item_group.py | 20 ++++---- .../warehouse_wise_stock_value.py | 20 ++++---- erpnext/stock/doctype/batch/batch.py | 31 +++++++------ .../doctype/delivery_note/delivery_note.py | 23 ++++++---- .../doctype/delivery_trip/delivery_trip.py | 10 ++-- .../inventory_dimension.py | 13 ++++-- erpnext/stock/doctype/item/item.py | 6 +-- .../item_alternative/item_alternative.py | 4 +- .../item_manufacturer/item_manufacturer.py | 2 +- .../landed_cost_voucher.py | 10 ++-- .../material_request/material_request.py | 34 +++++++++----- .../stock/doctype/packed_item/packed_item.py | 2 +- .../doctype/packing_slip/packing_slip.py | 2 +- erpnext/stock/doctype/pick_list/pick_list.py | 32 +++++++++---- .../purchase_receipt/purchase_receipt.py | 18 +++++--- .../doctype/putaway_rule/putaway_rule.py | 8 ++-- .../quality_inspection/quality_inspection.py | 10 ++-- .../quick_stock_balance.py | 3 +- .../repost_item_valuation.py | 2 +- .../serial_and_batch_bundle.py | 40 +++++++++++----- erpnext/stock/doctype/serial_no/serial_no.py | 2 +- erpnext/stock/doctype/shipment/shipment.py | 6 +-- .../stock/doctype/stock_entry/stock_entry.py | 22 +++++---- .../stock_reconciliation.py | 25 +++++++--- erpnext/stock/doctype/warehouse/warehouse.py | 15 ++++-- erpnext/stock/get_item_details.py | 46 ++++++++++++------- .../incorrect_serial_and_batch_bundle.py | 2 +- .../serial_and_batch_summary.py | 8 ++-- .../stock_and_account_value_comparison.py | 2 +- .../stock_ledger_invariant_check.py | 2 +- .../stock_qty_vs_batch_qty.py | 2 +- erpnext/stock/utils.py | 20 ++++---- 34 files changed, 294 insertions(+), 169 deletions(-) diff --git a/erpnext/stock/dashboard/item_dashboard.py b/erpnext/stock/dashboard/item_dashboard.py index d77ed7a6212..279a0017c03 100644 --- a/erpnext/stock/dashboard/item_dashboard.py +++ b/erpnext/stock/dashboard/item_dashboard.py @@ -9,7 +9,12 @@ from erpnext.stock.doctype.stock_reservation_entry.stock_reservation_entry impor @frappe.whitelist() def get_data( - item_code=None, warehouse=None, item_group=None, start=0, sort_by="actual_qty", sort_order="desc" + item_code: str | None = None, + warehouse: str | None = None, + item_group: str | None = None, + start: int = 0, + sort_by: str = "actual_qty", + sort_order: str = "desc", ): """Return data to render the item dashboard""" filters = [] diff --git a/erpnext/stock/dashboard/warehouse_capacity_dashboard.py b/erpnext/stock/dashboard/warehouse_capacity_dashboard.py index 75b2951e30b..cbebc99ba55 100644 --- a/erpnext/stock/dashboard/warehouse_capacity_dashboard.py +++ b/erpnext/stock/dashboard/warehouse_capacity_dashboard.py @@ -7,13 +7,13 @@ from erpnext.stock.utils import get_stock_balance @frappe.whitelist() def get_data( - item_code=None, - warehouse=None, - parent_warehouse=None, - company=None, - start=0, - sort_by="stock_capacity", - sort_order="desc", + item_code: str | None = None, + warehouse: str | None = None, + parent_warehouse: str | None = None, + company: str | None = None, + start: int = 0, + sort_by: str = "stock_capacity", + sort_order: str = "desc", ): """Return data to render the warehouse capacity dashboard.""" filters = get_filters(item_code, warehouse, parent_warehouse, company) diff --git a/erpnext/stock/dashboard_chart_source/stock_value_by_item_group/stock_value_by_item_group.py b/erpnext/stock/dashboard_chart_source/stock_value_by_item_group/stock_value_by_item_group.py index af760516ffd..f0123632df9 100644 --- a/erpnext/stock/dashboard_chart_source/stock_value_by_item_group/stock_value_by_item_group.py +++ b/erpnext/stock/dashboard_chart_source/stock_value_by_item_group/stock_value_by_item_group.py @@ -2,6 +2,8 @@ # License: GNU General Public License v3. See license.txt +from typing import Any + import frappe from frappe import _ from frappe.query_builder.functions import Sum @@ -11,15 +13,15 @@ from frappe.utils.dashboard import cache_source @frappe.whitelist() @cache_source def get( - chart_name=None, - chart=None, - no_cache=None, - filters=None, - from_date=None, - to_date=None, - timespan=None, - time_interval=None, - heatmap_year=None, + chart_name: str | None = None, + chart: Any = None, + no_cache: Any = None, + filters: dict | str | None = None, + from_date: Any = None, + to_date: Any = None, + timespan: Any = None, + time_interval: Any = None, + heatmap_year: Any = None, ): if filters and isinstance(filters, str): filters = frappe.parse_json(filters) diff --git a/erpnext/stock/dashboard_chart_source/warehouse_wise_stock_value/warehouse_wise_stock_value.py b/erpnext/stock/dashboard_chart_source/warehouse_wise_stock_value/warehouse_wise_stock_value.py index 13ac541256e..ebbef531154 100644 --- a/erpnext/stock/dashboard_chart_source/warehouse_wise_stock_value/warehouse_wise_stock_value.py +++ b/erpnext/stock/dashboard_chart_source/warehouse_wise_stock_value/warehouse_wise_stock_value.py @@ -2,6 +2,8 @@ # License: GNU General Public License v3. See license.txt +from typing import Any + import frappe from frappe import _ from frappe.utils.dashboard import cache_source @@ -10,15 +12,15 @@ from frappe.utils.dashboard import cache_source @frappe.whitelist() @cache_source def get( - chart_name=None, - chart=None, - no_cache=None, - filters=None, - from_date=None, - to_date=None, - timespan=None, - time_interval=None, - heatmap_year=None, + chart_name: str | None = None, + chart: Any | None = None, + no_cache: Any | None = None, + filters: dict | str | None = None, + from_date: Any | None = None, + to_date: Any | None = None, + timespan: Any | None = None, + time_interval: Any | None = None, + heatmap_year: Any | None = None, ): labels, datapoints = [], [] filters = frappe.parse_json(filters) diff --git a/erpnext/stock/doctype/batch/batch.py b/erpnext/stock/doctype/batch/batch.py index c67060a8699..b3df23bf2f4 100644 --- a/erpnext/stock/doctype/batch/batch.py +++ b/erpnext/stock/doctype/batch/batch.py @@ -2,6 +2,7 @@ # License: GNU General Public License v3. See license.txt +import datetime from collections import OrderedDict, defaultdict import frappe @@ -10,7 +11,7 @@ from frappe.model.document import Document from frappe.model.naming import make_autoname, revert_series_if_last from frappe.query_builder.functions import CurDate, Sum from frappe.utils import cint, flt, get_link_to_form -from frappe.utils.data import add_days +from frappe.utils.data import DateTimeLikeObject, add_days from frappe.utils.jinja import render_template @@ -235,18 +236,18 @@ class Batch(Document): @frappe.whitelist() def get_batch_qty( - batch_no=None, - warehouse=None, - item_code=None, - creation=None, - posting_datetime=None, - posting_date=None, - posting_time=None, - ignore_voucher_nos=None, - for_stock_levels=False, - consider_negative_batches=False, - do_not_check_future_batches=False, - ignore_reserved_stock=False, + batch_no: str | None = None, + warehouse: str | None = None, + item_code: str | None = None, + creation: DateTimeLikeObject | None = None, + posting_datetime: DateTimeLikeObject | None = None, + posting_date: DateTimeLikeObject | None = None, + posting_time: datetime.timedelta | None = None, + ignore_voucher_nos: list | None = None, + for_stock_levels: bool = False, + consider_negative_batches: bool = False, + do_not_check_future_batches: bool = False, + ignore_reserved_stock: bool = False, ): """Returns batch actual qty if warehouse is passed, or returns dict of qty by warehouse if warehouse is None @@ -295,7 +296,7 @@ def get_batch_qty( @frappe.whitelist() -def get_batches_by_oldest(item_code, warehouse): +def get_batches_by_oldest(item_code: str, warehouse: str): """Returns the oldest batch and qty for the given item_code and warehouse""" batches = get_batch_qty(item_code=item_code, warehouse=warehouse) batches_dates = [[batch, frappe.get_value("Batch", batch.batch_no, "expiry_date")] for batch in batches] @@ -447,7 +448,7 @@ def make_batch(kwargs): @frappe.whitelist() -def get_pos_reserved_batch_qty(filters): +def get_pos_reserved_batch_qty(filters: dict | str): import json if isinstance(filters, str): diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py index 07c1623a182..9e92054c741 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/delivery_note.py @@ -8,6 +8,7 @@ import frappe from frappe import _ from frappe.contacts.doctype.address.address import get_company_address from frappe.desk.notifications import clear_doctype_notifications +from frappe.model.document import Document from frappe.model.mapper import get_mapped_doc from frappe.model.utils import get_fetch_values from frappe.query_builder import DocType @@ -846,7 +847,9 @@ def get_returned_qty_map(delivery_note): @frappe.whitelist() -def make_sales_invoice(source_name, target_doc=None, args=None): +def make_sales_invoice( + source_name: str, target_doc: str | Document | None = None, args: dict | str | None = None +): if args is None: args = {} if isinstance(args, str): @@ -975,7 +978,9 @@ def make_sales_invoice(source_name, target_doc=None, args=None): @frappe.whitelist() -def make_delivery_trip(source_name, target_doc=None, kwargs=None): +def make_delivery_trip( + source_name: str, target_doc: str | Document | None = None, kwargs: dict | None = None +): if not target_doc: target_doc = frappe.new_doc("Delivery Trip") doclist = get_mapped_doc( @@ -1001,7 +1006,9 @@ def make_delivery_trip(source_name, target_doc=None, kwargs=None): @frappe.whitelist() -def make_installation_note(source_name, target_doc=None, kwargs=None): +def make_installation_note( + source_name: str, target_doc: str | Document | None = None, kwargs: dict | None = None +): def update_item(obj, target, source_parent): target.qty = flt(obj.qty) - flt(obj.installed_qty) target.serial_no = obj.serial_no @@ -1029,7 +1036,7 @@ def make_installation_note(source_name, target_doc=None, kwargs=None): @frappe.whitelist() -def make_packing_slip(source_name, target_doc=None): +def make_packing_slip(source_name: str, target_doc: str | Document | None = None): def set_missing_values(source, target): target.run_method("set_missing_values") @@ -1084,7 +1091,7 @@ def make_packing_slip(source_name, target_doc=None): @frappe.whitelist() -def make_shipment(source_name, target_doc=None): +def make_shipment(source_name: str, target_doc: str | Document | None = None): def postprocess(source, target): user = frappe.db.get_value( "User", frappe.session.user, ["email", "full_name", "phone", "mobile_no"], as_dict=1 @@ -1159,20 +1166,20 @@ def make_shipment(source_name, target_doc=None): @frappe.whitelist() -def make_sales_return(source_name, target_doc=None): +def make_sales_return(source_name: str, target_doc: str | Document | None = None): from erpnext.controllers.sales_and_purchase_return import make_return_doc return make_return_doc("Delivery Note", source_name, target_doc) @frappe.whitelist() -def update_delivery_note_status(docname, status): +def update_delivery_note_status(docname: str, status: str): dn = frappe.get_lazy_doc("Delivery Note", docname) dn.update_status(status) @frappe.whitelist() -def make_inter_company_purchase_receipt(source_name, target_doc=None): +def make_inter_company_purchase_receipt(source_name: str, target_doc: str | Document | None = None): return make_inter_company_transaction("Delivery Note", source_name, target_doc) diff --git a/erpnext/stock/doctype/delivery_trip/delivery_trip.py b/erpnext/stock/doctype/delivery_trip/delivery_trip.py index 24223e123f2..e59472c5294 100644 --- a/erpnext/stock/doctype/delivery_trip/delivery_trip.py +++ b/erpnext/stock/doctype/delivery_trip/delivery_trip.py @@ -150,7 +150,7 @@ class DeliveryTrip(Document): frappe.msgprint(_("Delivery Notes {0} updated").format(", ".join(delivery_notes_updated))) @frappe.whitelist() - def process_route(self, optimize): + def process_route(self, optimize: bool): """ Estimate the arrival times for each stop in the Delivery Trip. If `optimize` is True, the stops will be re-arranged, based @@ -305,7 +305,7 @@ class DeliveryTrip(Document): @frappe.whitelist() -def get_contact_and_address(name): +def get_contact_and_address(name: str): out = frappe._dict() get_default_contact(out, name) @@ -367,7 +367,7 @@ def get_default_address(out, name): @frappe.whitelist() -def get_contact_display(contact): +def get_contact_display(contact: str): contact_info = frappe.db.get_value( "Contact", contact, ["first_name", "last_name", "phone", "mobile_no"], as_dict=1 ) @@ -403,7 +403,7 @@ def sanitize_address(address): @frappe.whitelist() -def notify_customers(delivery_trip): +def notify_customers(delivery_trip: str): delivery_trip = frappe.get_doc("Delivery Trip", delivery_trip) context = delivery_trip.as_dict() @@ -468,7 +468,7 @@ def get_attachments(delivery_stop): @frappe.whitelist() -def get_driver_email(driver): +def get_driver_email(driver: str): employee = frappe.db.get_value("Driver", driver, "employee") email = frappe.db.get_value("Employee", employee, "prefered_email") return {"email": email} diff --git a/erpnext/stock/doctype/inventory_dimension/inventory_dimension.py b/erpnext/stock/doctype/inventory_dimension/inventory_dimension.py index 469e4d5e53a..6f3bdc7dc7d 100644 --- a/erpnext/stock/doctype/inventory_dimension/inventory_dimension.py +++ b/erpnext/stock/doctype/inventory_dimension/inventory_dimension.py @@ -1,6 +1,8 @@ # Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt +from typing import Any + import frappe from frappe import _, bold, scrub from frappe.custom.doctype.custom_field.custom_field import create_custom_fields @@ -306,7 +308,12 @@ def field_exists(doctype, fieldname) -> str or None: @frappe.whitelist() def get_inventory_documents( - doctype=None, txt=None, searchfield=None, start=None, page_len=None, filters=None + doctype: Any | None = None, + txt: str | None = None, + searchfield: str | None = None, + start: int | None = None, + page_len: int | None = None, + filters: dict | None = None, ): and_filters = [["DocField", "parent", "not in", ["Batch", "Serial No", "Item Price"]]] or_filters = [ @@ -395,13 +402,13 @@ def get_inventory_dimensions(): @frappe.whitelist() -def delete_dimension(dimension): +def delete_dimension(dimension: str): doc = frappe.get_doc("Inventory Dimension", dimension) doc.delete() @frappe.whitelist() -def get_parent_fields(child_doctype, dimension_name): +def get_parent_fields(child_doctype: str, dimension_name: str): parent_doctypes = frappe.get_all("DocField", fields=["parent"], filters={"options": child_doctype}) fields = [] diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index e9e82a3c08b..327e1bb09c4 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -1341,7 +1341,7 @@ def set_item_default(item_code, company, fieldname, value): @frappe.whitelist() -def get_item_details(item_code, company=None): +def get_item_details(item_code: str, company: str | None = None): out = frappe._dict() if company: out = get_item_defaults(item_code, company) or frappe._dict() @@ -1353,7 +1353,7 @@ def get_item_details(item_code, company=None): @frappe.whitelist() -def get_uom_conv_factor(uom, stock_uom): +def get_uom_conv_factor(uom: str | None, stock_uom: str | None): """Get UOM conversion factor from uom to stock_uom e.g. uom = "Kg", stock_uom = "Gram" then returns 1000.0 """ @@ -1399,7 +1399,7 @@ def get_uom_conv_factor(uom, stock_uom): @frappe.whitelist() -def get_item_attribute(parent, attribute_value=""): +def get_item_attribute(parent: str, attribute_value: str = ""): """Used for providing auto-completions in child table.""" if not frappe.has_permission("Item"): frappe.throw(_("No Permission")) diff --git a/erpnext/stock/doctype/item_alternative/item_alternative.py b/erpnext/stock/doctype/item_alternative/item_alternative.py index a73a82fc1e6..b2923b4a828 100644 --- a/erpnext/stock/doctype/item_alternative/item_alternative.py +++ b/erpnext/stock/doctype/item_alternative/item_alternative.py @@ -2,6 +2,8 @@ # For license information, please see license.txt +from typing import Any + import frappe from frappe import _ from frappe.model.document import Document @@ -83,7 +85,7 @@ class ItemAlternative(Document): @frappe.whitelist() @frappe.validate_and_sanitize_search_inputs -def get_alternative_items(doctype, txt, searchfield, start, page_len, filters): +def get_alternative_items(doctype: Any, txt: str, searchfield: Any, start: int, page_len: int, filters: dict): return frappe.db.sql( f""" (select alternative_item_code from `tabItem Alternative` where item_code = %(item_code)s and alternative_item_code like %(txt)s) diff --git a/erpnext/stock/doctype/item_manufacturer/item_manufacturer.py b/erpnext/stock/doctype/item_manufacturer/item_manufacturer.py index 715f09b9356..f6f77db1f39 100644 --- a/erpnext/stock/doctype/item_manufacturer/item_manufacturer.py +++ b/erpnext/stock/doctype/item_manufacturer/item_manufacturer.py @@ -86,7 +86,7 @@ class ItemManufacturer(Document): @frappe.whitelist() -def get_item_manufacturer_part_no(item_code, manufacturer): +def get_item_manufacturer_part_no(item_code: str, manufacturer: str): return frappe.db.get_value( "Item Manufacturer", {"item_code": item_code, "manufacturer": manufacturer}, diff --git a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py index a43223552b5..9bb1b485059 100644 --- a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py +++ b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py @@ -2,6 +2,8 @@ # For license information, please see license.txt +from typing import Any + import frappe from frappe import _ from frappe.model.document import Document @@ -221,7 +223,7 @@ class LandedCostVoucher(Document): ) @frappe.whitelist() - def get_receipt_document_details(self, receipt_document_type, receipt_document): + def get_receipt_document_details(self, receipt_document_type: str, receipt_document: str): if receipt_document_type in [ "Purchase Invoice", "Purchase Receipt", @@ -356,7 +358,7 @@ class LandedCostVoucher(Document): ) @frappe.whitelist() - def get_vendor_invoice_amount(self, vendor_invoice): + def get_vendor_invoice_amount(self, vendor_invoice: str): filters = frappe._dict( { "name": vendor_invoice, @@ -427,7 +429,9 @@ def get_pr_items(purchase_receipt): @frappe.whitelist() @frappe.validate_and_sanitize_search_inputs -def get_vendor_invoices(doctype, txt, searchfield, start, page_len, filters): +def get_vendor_invoices( + doctype: str, txt: str | None, searchfield: Any, start: int, page_len: int, filters: dict +): if not frappe.has_permission("Purchase Invoice", "read"): return [] diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py index 1868730ffd3..d76689d0c62 100644 --- a/erpnext/stock/doctype/material_request/material_request.py +++ b/erpnext/stock/doctype/material_request/material_request.py @@ -6,10 +6,12 @@ import json +from typing import Any import frappe import frappe.defaults from frappe import _, msgprint +from frappe.model.document import Document from frappe.model.mapper import get_mapped_doc from frappe.query_builder import Order from frappe.query_builder.functions import Sum @@ -479,14 +481,16 @@ def get_list_context(context=None): @frappe.whitelist() -def update_status(name, status): +def update_status(name: str, status: str): material_request = frappe.get_doc("Material Request", name) material_request.check_permission("write") material_request.update_status(status) @frappe.whitelist() -def make_purchase_order(source_name, target_doc=None, args=None): +def make_purchase_order( + source_name: str, target_doc: str | Document | None = None, args: dict | str | None = None +): if args is None: args = {} if isinstance(args, str): @@ -563,7 +567,7 @@ def make_purchase_order(source_name, target_doc=None, args=None): @frappe.whitelist() -def make_request_for_quotation(source_name, target_doc=None): +def make_request_for_quotation(source_name: str, target_doc: str | Document | None = None): doclist = get_mapped_doc( "Material Request", source_name, @@ -588,7 +592,9 @@ def make_request_for_quotation(source_name, target_doc=None): @frappe.whitelist() -def make_purchase_order_based_on_supplier(source_name, target_doc=None, args=None): +def make_purchase_order_based_on_supplier( + source_name: str, target_doc: str | Document | None = None, args: dict | None = None +): mr = source_name supplier_items = get_items_based_on_default_supplier(args.get("supplier")) @@ -631,7 +637,7 @@ def make_purchase_order_based_on_supplier(source_name, target_doc=None, args=Non @frappe.whitelist() -def get_items_based_on_default_supplier(supplier): +def get_items_based_on_default_supplier(supplier: str): supplier_items = [ d.parent for d in frappe.db.get_all( @@ -644,7 +650,9 @@ def get_items_based_on_default_supplier(supplier): @frappe.whitelist() @frappe.validate_and_sanitize_search_inputs -def get_material_requests_based_on_supplier(doctype, txt, searchfield, start, page_len, filters): +def get_material_requests_based_on_supplier( + doctype: Any, txt: str, searchfield: Any, start: int, page_len: int, filters: dict +): supplier = filters.get("supplier") supplier_items = get_items_based_on_default_supplier(supplier) @@ -688,7 +696,9 @@ def get_material_requests_based_on_supplier(doctype, txt, searchfield, start, pa @frappe.whitelist() @frappe.validate_and_sanitize_search_inputs -def get_default_supplier_query(doctype, txt, searchfield, start, page_len, filters): +def get_default_supplier_query( + doctype: Any, txt: str, searchfield: str, start: int, page_len: int, filters: dict +): doc = frappe.get_doc("Material Request", filters.get("doc")) item_list = [] for d in doc.items: @@ -718,7 +728,7 @@ def get_default_supplier_query(doctype, txt, searchfield, start, page_len, filte @frappe.whitelist() -def make_supplier_quotation(source_name, target_doc=None): +def make_supplier_quotation(source_name: str, target_doc: str | Document | None = None): def postprocess(source, target_doc): set_missing_values(source, target_doc) @@ -748,7 +758,7 @@ def make_supplier_quotation(source_name, target_doc=None): @frappe.whitelist() -def make_stock_entry(source_name, target_doc=None): +def make_stock_entry(source_name: str, target_doc: str | Document | None = None): def update_item(obj, target, source_parent): qty = ( flt(flt(obj.stock_qty) - flt(obj.ordered_qty)) / target.conversion_factor @@ -841,7 +851,7 @@ def make_stock_entry(source_name, target_doc=None): @frappe.whitelist() -def raise_work_orders(material_request, company): +def raise_work_orders(material_request: str, company: str): mr = frappe.get_doc("Material Request", material_request) errors = [] work_orders = [] @@ -912,7 +922,7 @@ def raise_work_orders(material_request, company): @frappe.whitelist() -def create_pick_list(source_name, target_doc=None): +def create_pick_list(source_name: str, target_doc: str | Document | None = None): def update_item(obj, target, source_parent): qty = flt((obj.stock_qty - obj.picked_qty) / target.conversion_factor, obj.precision("qty")) target.qty = qty @@ -951,7 +961,7 @@ def create_pick_list(source_name, target_doc=None): @frappe.whitelist() -def make_in_transit_stock_entry(source_name, in_transit_warehouse): +def make_in_transit_stock_entry(source_name: str, in_transit_warehouse: str): ste_doc = make_stock_entry(source_name) ste_doc.add_to_transit = 1 ste_doc.to_warehouse = in_transit_warehouse diff --git a/erpnext/stock/doctype/packed_item/packed_item.py b/erpnext/stock/doctype/packed_item/packed_item.py index 9477b85131d..455ea9e96bf 100644 --- a/erpnext/stock/doctype/packed_item/packed_item.py +++ b/erpnext/stock/doctype/packed_item/packed_item.py @@ -366,7 +366,7 @@ def on_doctype_update(): @frappe.whitelist() -def get_items_from_product_bundle(row): +def get_items_from_product_bundle(row: str): row, items = ItemDetailsCtx(json.loads(row)), [] bundled_items = get_product_bundle_items(row["item_code"]) diff --git a/erpnext/stock/doctype/packing_slip/packing_slip.py b/erpnext/stock/doctype/packing_slip/packing_slip.py index 587d7ecd337..9544a7a3766 100644 --- a/erpnext/stock/doctype/packing_slip/packing_slip.py +++ b/erpnext/stock/doctype/packing_slip/packing_slip.py @@ -206,7 +206,7 @@ class PackingSlip(StatusUpdater): @frappe.whitelist() @frappe.validate_and_sanitize_search_inputs -def item_details(doctype, txt, searchfield, start, page_len, filters): +def item_details(doctype: str, txt: str, searchfield: str, start: int, page_len: int, filters: dict): from erpnext.controllers.queries import get_match_cond return frappe.db.sql( diff --git a/erpnext/stock/doctype/pick_list/pick_list.py b/erpnext/stock/doctype/pick_list/pick_list.py index f71ab2d18f7..723cd0a6da2 100644 --- a/erpnext/stock/doctype/pick_list/pick_list.py +++ b/erpnext/stock/doctype/pick_list/pick_list.py @@ -4,9 +4,11 @@ import json from collections import OrderedDict, defaultdict from itertools import groupby +from typing import Any import frappe from frappe import _, bold +from frappe.model.document import Document from frappe.model.mapper import map_child_doc from frappe.query_builder import Case from frappe.query_builder.custom import GROUP_CONCAT @@ -428,7 +430,7 @@ class PickList(TransactionBase): frappe.get_doc("Sales Order", sales_order, for_update=True).update_picking_status() @frappe.whitelist() - def create_stock_reservation_entries(self, notify=True) -> None: + def create_stock_reservation_entries(self, notify: bool = True) -> None: """Creates Stock Reservation Entries for Sales Order Items against Pick List.""" so_items_details_map = {} @@ -455,7 +457,7 @@ class PickList(TransactionBase): ) @frappe.whitelist() - def cancel_stock_reservation_entries(self, notify=True) -> None: + def cancel_stock_reservation_entries(self, notify: bool = True) -> None: """Cancel Stock Reservation Entries for Sales Order Items created against Pick List.""" from erpnext.stock.doctype.stock_reservation_entry.stock_reservation_entry import ( @@ -480,7 +482,7 @@ class PickList(TransactionBase): ) @frappe.whitelist() - def set_item_locations(self, save=False): + def set_item_locations(self, save: bool = False): self.validate_for_qty() items = self.aggregate_item_qty() picked_items_details = self.get_picked_items_details(items) @@ -1209,7 +1211,7 @@ def get_available_item_locations_for_other_item( @frappe.whitelist() -def create_delivery_note(source_name, target_doc=None): +def create_delivery_note(source_name: str, target_doc: str | Document | None = None): pick_list = frappe.get_doc("Pick List", source_name) validate_item_locations(pick_list) sales_dict = dict() @@ -1280,7 +1282,9 @@ def create_dn_wo_so(pick_list, delivery_note=None): @frappe.whitelist() -def create_dn_for_pick_lists(source_name, target_doc=None, kwargs=None): +def create_dn_for_pick_lists( + source_name: str, target_doc: str | Document | None = None, kwargs: dict | str | None = None +): """Get Items from Multiple Pick Lists and create a Delivery Note for filtered customer""" if kwargs is None: kwargs = {} @@ -1428,7 +1432,7 @@ def add_product_bundles_to_delivery_note( @frappe.whitelist() -def create_stock_entry(pick_list): +def create_stock_entry(pick_list: str): pick_list = frappe.get_doc(json.loads(pick_list)) validate_item_locations(pick_list) @@ -1454,7 +1458,15 @@ def create_stock_entry(pick_list): @frappe.whitelist() -def get_pending_work_orders(doctype, txt, searchfield, start, page_length, filters, as_dict): +def get_pending_work_orders( + doctype: Any, + txt: str, + searchfield: str, + start: int, + page_length: int, + filters: dict, + as_dict: bool = False, +): wo = frappe.qb.DocType("Work Order") return ( frappe.qb.from_(wo) @@ -1474,7 +1486,9 @@ def get_pending_work_orders(doctype, txt, searchfield, start, page_length, filte @frappe.whitelist() -def get_item_details(item_code, uom=None, warehouse=None, company=None): +def get_item_details( + item_code: str, uom: str | None = None, warehouse: str | None = None, company: str | None = None +): details = frappe.db.get_value("Item", item_code, "stock_uom", as_dict=1) details.uom = uom or details.stock_uom if uom: @@ -1610,7 +1624,7 @@ def get_rejected_warehouses(): @frappe.whitelist() -def get_pick_list_query(doctype, txt, searchfield, start, page_len, filters): +def get_pick_list_query(doctype: Any, txt: str, searchfield: Any, start: int, page_len: int, filters: dict): frappe.has_permission("Pick List", throw=True) if not filters.get("company"): diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index f3e56c3b239..11d0c163a0a 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -7,6 +7,7 @@ import json import frappe from frappe import _, throw from frappe.desk.notifications import clear_doctype_notifications +from frappe.model.document import Document from frappe.model.mapper import get_mapped_doc from frappe.query_builder.functions import Abs, CombineDatetime, Sum from frappe.utils import cint, flt, get_datetime, getdate, nowdate @@ -246,7 +247,8 @@ class PurchaseReceipt(BuyingController): from erpnext.stock.doctype.putaway_rule.putaway_rule import apply_putaway_rule if self.get("items") and self.apply_putaway_rule and not self.get("is_return"): - apply_putaway_rule(self.doctype, self.get("items"), self.company) + if items := apply_putaway_rule(self.doctype, self.get("items"), self.company): + self.items = items def validate(self): self.validate_posting_time() @@ -1401,7 +1403,9 @@ def get_item_wise_returned_qty(pr_doc): @frappe.whitelist() -def make_purchase_invoice(source_name, target_doc=None, args=None): +def make_purchase_invoice( + source_name: str | None, target_doc: str | Document | None = None, args: dict | str | None = None +): if args is None: args = {} if isinstance(args, str): @@ -1554,14 +1558,14 @@ def get_returned_qty_map(purchase_receipt): @frappe.whitelist() -def make_purchase_return_against_rejected_warehouse(source_name): +def make_purchase_return_against_rejected_warehouse(source_name: str): from erpnext.controllers.sales_and_purchase_return import make_return_doc return make_return_doc("Purchase Receipt", source_name, return_against_rejected_qty=True) @frappe.whitelist() -def make_purchase_return(source_name, target_doc=None): +def make_purchase_return(source_name: str, target_doc: str | Document | None = None): from erpnext.controllers.sales_and_purchase_return import make_return_doc return make_return_doc("Purchase Receipt", source_name, target_doc) @@ -1574,7 +1578,7 @@ def update_purchase_receipt_status(docname, status): @frappe.whitelist() -def make_stock_entry(source_name, target_doc=None): +def make_stock_entry(source_name: str, target_doc: str | Document | None = None): def set_missing_values(source, target): target.stock_entry_type = "Material Transfer" target.purpose = "Material Transfer" @@ -1634,7 +1638,7 @@ def make_stock_entry(source_name, target_doc=None): @frappe.whitelist() -def make_inter_company_delivery_note(source_name, target_doc=None): +def make_inter_company_delivery_note(source_name: str, target_doc: str | Document | None = None): return make_inter_company_transaction("Purchase Receipt", source_name, target_doc) @@ -1644,7 +1648,7 @@ def update_regional_gl_entries(gl_list, doc): @frappe.whitelist() -def make_lcv(doctype, docname): +def make_lcv(doctype: str, docname: str): landed_cost_voucher = frappe.new_doc("Landed Cost Voucher") details = frappe.db.get_value(doctype, docname, ["supplier", "company", "base_grand_total"], as_dict=1) diff --git a/erpnext/stock/doctype/putaway_rule/putaway_rule.py b/erpnext/stock/doctype/putaway_rule/putaway_rule.py index c78842a5fe2..382b7106552 100644 --- a/erpnext/stock/doctype/putaway_rule/putaway_rule.py +++ b/erpnext/stock/doctype/putaway_rule/putaway_rule.py @@ -90,7 +90,7 @@ class PutawayRule(Document): @frappe.whitelist() -def get_available_putaway_capacity(rule): +def get_available_putaway_capacity(rule: str): stock_capacity, item_code, warehouse = frappe.db.get_value( "Putaway Rule", rule, ["stock_capacity", "item_code", "warehouse"] ) @@ -100,7 +100,9 @@ def get_available_putaway_capacity(rule): @frappe.whitelist() -def apply_putaway_rule(doctype, items, company, sync=None, purpose=None): +def apply_putaway_rule( + doctype: str, items: list | str, company: str, sync: str | bool | None = None, purpose: str | None = None +): """Applies Putaway Rule on line items. items: List of Purchase Receipt/Stock Entry Items @@ -193,8 +195,8 @@ def apply_putaway_rule(doctype, items, company, sync=None, purpose=None): show_unassigned_items_message(items_not_accomodated) if updated_table and _items_changed(items, updated_table, doctype): - items[:] = updated_table frappe.msgprint(_("Applied putaway rules."), alert=True) + return updated_table if sync and json.loads(sync): # sync with client side return items diff --git a/erpnext/stock/doctype/quality_inspection/quality_inspection.py b/erpnext/stock/doctype/quality_inspection/quality_inspection.py index 67fc49acb8a..127164509a8 100644 --- a/erpnext/stock/doctype/quality_inspection/quality_inspection.py +++ b/erpnext/stock/doctype/quality_inspection/quality_inspection.py @@ -2,6 +2,8 @@ # License: GNU General Public License v3. See license.txt +from typing import Any + import frappe from frappe import _ from frappe.model.document import Document @@ -364,7 +366,7 @@ class QualityInspection(Document): @frappe.whitelist() @frappe.validate_and_sanitize_search_inputs -def item_query(doctype, txt, searchfield, start, page_len, filters): +def item_query(doctype: Any, txt: str | None, searchfield: Any, start: int, page_len: int, filters: dict): from frappe.desk.reportview import get_match_cond from_doctype = cstr(filters.get("from")) @@ -420,7 +422,9 @@ def item_query(doctype, txt, searchfield, start, page_len, filters): @frappe.whitelist() @frappe.validate_and_sanitize_search_inputs -def quality_inspection_query(doctype, txt, searchfield, start, page_len, filters): +def quality_inspection_query( + doctype: Any, txt: str | None, searchfield: Any, start: int, page_len: int, filters: dict +): return frappe.get_all( "Quality Inspection", limit_start=start, @@ -437,7 +441,7 @@ def quality_inspection_query(doctype, txt, searchfield, start, page_len, filters @frappe.whitelist() -def make_quality_inspection(source_name, target_doc=None): +def make_quality_inspection(source_name: str, target_doc: Document | str | None = None): def postprocess(source, doc): doc.inspected_by = frappe.session.user doc.get_quality_inspection_template() diff --git a/erpnext/stock/doctype/quick_stock_balance/quick_stock_balance.py b/erpnext/stock/doctype/quick_stock_balance/quick_stock_balance.py index 7b7bffe91eb..ecd016a4ecf 100644 --- a/erpnext/stock/doctype/quick_stock_balance/quick_stock_balance.py +++ b/erpnext/stock/doctype/quick_stock_balance/quick_stock_balance.py @@ -5,6 +5,7 @@ import frappe from frappe import _ from frappe.model.document import Document +from frappe.utils.data import DateTimeLikeObject from erpnext.stock.utils import get_stock_balance, get_stock_value_on @@ -32,7 +33,7 @@ class QuickStockBalance(Document): @frappe.whitelist() -def get_stock_item_details(warehouse, date, item=None, barcode=None): +def get_stock_item_details(warehouse: str, date: str, item: str | None = None, barcode: str | None = None): out = {} if barcode: out["item"] = frappe.db.get_value("Item Barcode", filters={"barcode": barcode}, fieldname=["parent"]) diff --git a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py index 7be0b09169e..a83b25a1450 100644 --- a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py +++ b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py @@ -332,7 +332,7 @@ class RepostItemValuation(Document): @frappe.whitelist() -def bulk_restart_reposting(names): +def bulk_restart_reposting(names: str): names = json.loads(names) for name in names: doc = frappe.get_doc("Repost Item Valuation", name) diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py index c38a73a13eb..9e4063d6b27 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py +++ b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py @@ -5,6 +5,7 @@ import collections import csv import json from collections import Counter, defaultdict +from typing import Any import frappe import frappe.query_builder @@ -27,6 +28,7 @@ from frappe.utils import ( ) from frappe.utils.csvutils import build_csv_response +from erpnext.stock.doctype.purchase_receipt_item.purchase_receipt_item import PurchaseReceiptItem from erpnext.stock.serial_batch_bundle import ( BatchNoValuation, SerialNoValuation, @@ -1631,7 +1633,7 @@ class SerialandBatchBundle(Document): self.delink_reference_from_batch() @frappe.whitelist() - def add_serial_batch(self, data): + def add_serial_batch(self, data: str | dict): serial_nos, batch_nos = [], [] if isinstance(data, str): data = parse_json(data) @@ -1658,7 +1660,7 @@ class SerialandBatchBundle(Document): @frappe.whitelist() -def download_blank_csv_template(content): +def download_blank_csv_template(content: str | list): csv_data = [] if isinstance(content, str): content = parse_json(content) @@ -1672,7 +1674,7 @@ def download_blank_csv_template(content): @frappe.whitelist() -def upload_csv_file(item_code, file_path): +def upload_csv_file(item_code: str, file_path: str): serial_nos, batch_nos = [], [] serial_nos, batch_nos = get_serial_batch_from_csv(item_code, file_path) @@ -1770,7 +1772,7 @@ def get_serial_batch_from_data(item_code, kwargs): @frappe.whitelist() -def create_serial_nos(item_code, serial_nos): +def create_serial_nos(item_code: str, serial_nos: list | str): serial_nos = get_serial_batch_from_data( item_code, { @@ -1887,7 +1889,9 @@ def make_batch_nos(item_code, batch_nos): @frappe.whitelist() @frappe.validate_and_sanitize_search_inputs -def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=False): +def item_query( + doctype: Any, txt: str, searchfield: str, start: int, page_len: int, filters: Any, as_dict: bool = False +): item_filters = {"disabled": 0} if txt: item_filters["name"] = ("like", f"%{txt}%") @@ -1902,7 +1906,13 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals @frappe.whitelist() -def get_serial_batch_ledgers(item_code=None, docstatus=None, voucher_no=None, name=None, child_row=None): +def get_serial_batch_ledgers( + item_code: str | None = None, + docstatus: str | list | int | None = None, + voucher_no: str | None = None, + name: str | list | None = None, + child_row: dict | str | None = None, +): filters = get_filters_for_bundle( item_code=item_code, docstatus=docstatus, voucher_no=voucher_no, name=name, child_row=child_row ) @@ -1978,7 +1988,13 @@ def get_reference_serial_and_batch_bundle(child_row): @frappe.whitelist() -def add_serial_batch_ledgers(entries, child_row, doc, warehouse, do_not_save=False) -> object: +def add_serial_batch_ledgers( + entries: list | str, + child_row: PurchaseReceiptItem | dict | str, + doc: Document, + warehouse: str | None = None, + do_not_save: bool = False, +): if isinstance(child_row, str): child_row = frappe._dict(parse_json(child_row)) @@ -2131,7 +2147,7 @@ def update_serial_batch_no_ledgers(bundle, entries, child_row, parent_doc, wareh @frappe.whitelist() -def update_serial_or_batch(bundle_id, serial_no=None, batch_no=None): +def update_serial_or_batch(bundle_id: str, serial_no: str | None = None, batch_no: str | None = None): if batch_no and not serial_no: if qty := frappe.db.get_value( "Serial and Batch Entry", {"parent": bundle_id, "batch_no": batch_no}, "qty" @@ -3303,12 +3319,14 @@ def get_stock_ledgers_batches(kwargs): @frappe.whitelist() -def get_batch_no_from_serial_no(serial_no): +def get_batch_no_from_serial_no(serial_no: str): return frappe.get_cached_value("Serial No", serial_no, "batch_no") @frappe.whitelist() -def is_serial_batch_no_exists(item_code, type_of_transaction, serial_no=None, batch_no=None): +def is_serial_batch_no_exists( + item_code: str, type_of_transaction: str, serial_no: str | None = None, batch_no: str | None = None +): if serial_no and not frappe.db.exists("Serial No", serial_no): if type_of_transaction != "Inward": frappe.throw(_("Serial No {0} does not exists").format(serial_no)) @@ -3337,7 +3355,7 @@ def make_batch_no(batch_no, item_code): @frappe.whitelist() -def is_duplicate_serial_no(bundle_id, serial_no): +def is_duplicate_serial_no(bundle_id: str, serial_no: str): return frappe.db.exists("Serial and Batch Entry", {"parent": bundle_id, "serial_no": serial_no}) diff --git a/erpnext/stock/doctype/serial_no/serial_no.py b/erpnext/stock/doctype/serial_no/serial_no.py index 42fef027aba..8a01b08575c 100644 --- a/erpnext/stock/doctype/serial_no/serial_no.py +++ b/erpnext/stock/doctype/serial_no/serial_no.py @@ -221,7 +221,7 @@ def auto_fetch_serial_number( @frappe.whitelist() -def get_pos_reserved_serial_nos(filters): +def get_pos_reserved_serial_nos(filters: str | dict): if isinstance(filters, str): filters = json.loads(filters) diff --git a/erpnext/stock/doctype/shipment/shipment.py b/erpnext/stock/doctype/shipment/shipment.py index ae5a4214d24..816293a388a 100644 --- a/erpnext/stock/doctype/shipment/shipment.py +++ b/erpnext/stock/doctype/shipment/shipment.py @@ -114,19 +114,19 @@ class Shipment(Document): @frappe.whitelist() -def get_address_name(ref_doctype, docname): +def get_address_name(ref_doctype: str, docname: str): # Return address name return get_party_shipping_address(ref_doctype, docname) @frappe.whitelist() -def get_contact_name(ref_doctype, docname): +def get_contact_name(ref_doctype: str, docname: str): # Return address name return get_default_contact(ref_doctype, docname) @frappe.whitelist() -def get_company_contact(user): +def get_company_contact(user: str): contact = frappe.db.get_value( "User", user, diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 2e2639080cf..eae822ab2da 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -7,6 +7,7 @@ from collections import defaultdict import frappe from frappe import _, bold +from frappe.model.document import Document from frappe.model.mapper import get_mapped_doc from frappe.query_builder import DocType from frappe.query_builder.functions import Sum @@ -215,7 +216,10 @@ class StockEntry(StockController, SubcontractingInwardController): apply_rule = self.apply_putaway_rule and (self.purpose in ["Material Transfer", "Material Receipt"]) if self.get("items") and apply_rule: - apply_putaway_rule(self.doctype, self.get("items"), self.company, purpose=self.purpose) + if items := apply_putaway_rule( + self.doctype, self.get("items"), self.company, purpose=self.purpose + ): + self.items = items if self.project: for item in self.items: @@ -2094,7 +2098,7 @@ class StockEntry(StockController, SubcontractingInwardController): return False @frappe.whitelist() - def get_item_details(self, args: ItemDetailsCtx = None, for_update=False): + def get_item_details(self, args: ItemDetailsCtx | None = None, for_update: bool = False): item = frappe.qb.DocType("Item") item_default = frappe.qb.DocType("Item Default") @@ -3515,7 +3519,7 @@ class StockEntry(StockController, SubcontractingInwardController): @frappe.whitelist() -def move_sample_to_retention_warehouse(company, items): +def move_sample_to_retention_warehouse(company: str, items: str | list): from erpnext.stock.serial_batch_bundle import ( SerialBatchCreation, get_batch_nos, @@ -3596,7 +3600,7 @@ def move_sample_to_retention_warehouse(company, items): @frappe.whitelist() -def make_stock_in_entry(source_name, target_doc=None): +def make_stock_in_entry(source_name: str, target_doc: str | Document | None = None): def set_missing_values(source, target): target.stock_entry_type = "Material Transfer" target.set_missing_values() @@ -3647,7 +3651,7 @@ def make_stock_in_entry(source_name, target_doc=None): @frappe.whitelist() -def get_work_order_details(work_order, company): +def get_work_order_details(work_order: str, company: str): work_order = frappe.get_doc("Work Order", work_order) pending_qty_to_produce = flt(work_order.qty) - flt(work_order.produced_qty) @@ -3766,7 +3770,7 @@ def get_valuation_rate_for_finished_good_entry(work_order): @frappe.whitelist() -def get_uom_details(item_code, uom, qty): +def get_uom_details(item_code: str, uom: str, qty: float | None): """Returns dict `{"conversion_factor": [value], "transfer_qty": qty * [value]}` :param args: dict with `item_code`, `uom` and `qty`""" conversion_factor = get_conversion_factor(item_code, uom).get("conversion_factor") @@ -3825,7 +3829,7 @@ def get_expired_batches(): @frappe.whitelist() -def get_warehouse_details(args): +def get_warehouse_details(args: str | dict): if isinstance(args, str): args = json.loads(args) @@ -3847,7 +3851,7 @@ def get_warehouse_details(args): @frappe.whitelist() -def validate_sample_quantity(item_code, sample_quantity, qty, batch_no=None): +def validate_sample_quantity(item_code: str, sample_quantity: int, qty: float, batch_no: str | None = None): if cint(qty) < cint(sample_quantity): frappe.throw( _("Sample quantity {0} cannot be more than received quantity {1}").format(sample_quantity, qty) @@ -3916,7 +3920,7 @@ def get_supplied_items( @frappe.whitelist() -def get_items_from_subcontract_order(source_name, target_doc=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 if isinstance(target_doc, str): diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py index bb8f6e9cc7a..bb9a749664f 100644 --- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py +++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py @@ -2,9 +2,12 @@ # License: GNU General Public License v3. See license.txt +from datetime import datetime, timedelta + import frappe from frappe import _, bold, json, msgprint from frappe.utils import add_to_date, cint, cstr, flt, now +from frappe.utils.data import DateTimeLikeObject import erpnext from erpnext.accounts.utils import get_company_default @@ -16,6 +19,7 @@ from erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle impor get_available_serial_nos, ) from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos +from erpnext.stock.doctype.stock_reconciliation_item.stock_reconciliation_item import StockReconciliationItem from erpnext.stock.utils import get_combine_datetime, get_incoming_rate, get_stock_balance @@ -1260,7 +1264,14 @@ def get_batch_qty_for_stock_reco( @frappe.whitelist() -def get_items(warehouse, posting_date, posting_time, company, item_code=None, ignore_empty_stock=False): +def get_items( + warehouse: str, + posting_date: DateTimeLikeObject, + posting_time: DateTimeLikeObject, + company: str, + item_code: str | None = None, + ignore_empty_stock: bool | str | int = False, +): ignore_empty_stock = cint(ignore_empty_stock) items = [] if item_code and warehouse: @@ -1426,13 +1437,13 @@ def get_itemwise_batch(warehouse, posting_date, company, item_code=None): def get_stock_balance_for( item_code: str, warehouse: str, - posting_date, - posting_time, + posting_date: DateTimeLikeObject, + posting_time: DateTimeLikeObject | timedelta, batch_no: str | None = None, with_valuation_rate: bool = True, - inventory_dimensions_dict=None, - row=None, - company=None, + inventory_dimensions_dict: dict | None = None, + row: StockReconciliationItem | str | dict | None = None, + company: str | None = None, ): frappe.has_permission("Stock Reconciliation", "write", throw=True) @@ -1519,7 +1530,7 @@ def get_stock_balance_for( @frappe.whitelist() -def get_difference_account(purpose, company): +def get_difference_account(purpose: str, company: str): if purpose == "Stock Reconciliation": account = get_company_default(company, "stock_adjustment_account") else: diff --git a/erpnext/stock/doctype/warehouse/warehouse.py b/erpnext/stock/doctype/warehouse/warehouse.py index c2c553457b0..79cabd4d3e4 100644 --- a/erpnext/stock/doctype/warehouse/warehouse.py +++ b/erpnext/stock/doctype/warehouse/warehouse.py @@ -3,6 +3,7 @@ import json +from typing import Any import frappe from frappe import _, throw @@ -191,7 +192,13 @@ class Warehouse(NestedSet): @frappe.whitelist() -def get_children(doctype, parent=None, company=None, is_root=False, include_disabled=False): +def get_children( + doctype: str, + parent: str | None = None, + company: str | None = None, + is_root: bool = False, + include_disabled: bool | str = False, +): if is_root: parent = "" @@ -224,7 +231,7 @@ def add_node(): @frappe.whitelist() -def convert_to_group_or_ledger(docname=None): +def convert_to_group_or_ledger(docname: str | None = None): if not docname: docname = frappe.form_dict.docname return frappe.get_doc("Warehouse", docname).convert_to_group_or_ledger() @@ -299,7 +306,9 @@ def apply_warehouse_filter(query, sle, filters): @frappe.whitelist() @frappe.validate_and_sanitize_search_inputs -def get_warehouses_for_reorder(doctype, txt, searchfield, start, page_len, filters): +def get_warehouses_for_reorder( + doctype: str, txt: Any, searchfield: Any, start: int, page_len: int, filters: dict +): filters = frappe._dict(filters or {}) if filters.warehouse and not frappe.db.exists("Warehouse", filters.warehouse): diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index 085eab4fd1f..121922574eb 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -3,6 +3,7 @@ import json +from typing import Any import frappe from frappe import _, throw @@ -54,7 +55,12 @@ def _preprocess_ctx(ctx): @frappe.whitelist() @erpnext.normalize_ctx_input(ItemDetailsCtx) -def get_item_details(ctx, doc=None, for_validate=False, overwrite_warehouse=True) -> ItemDetails: +def get_item_details( + ctx: ItemDetailsCtx, + doc: Document | str | None = None, + for_validate: bool = False, + overwrite_warehouse: bool = True, +): """ ctx = { "item_code": "", @@ -649,7 +655,13 @@ def get_barcode_data(items_list=None, item_code=None): @frappe.whitelist() -def get_item_tax_info(doc, tax_category, item_codes, item_rates=None, item_tax_templates=None): +def get_item_tax_info( + doc: Document | str | None, + tax_category: str, + item_codes: list, + item_rates: dict | None = None, + item_tax_templates: dict | None = None, +): out = {} if item_tax_templates is None: @@ -690,7 +702,7 @@ def get_item_tax_info(doc, tax_category, item_codes, item_rates=None, item_tax_t @frappe.whitelist() @erpnext.normalize_ctx_input(ItemDetailsCtx) -def get_item_tax_template(ctx, item=None, out: ItemDetails | None = None): +def get_item_tax_template(ctx: ItemDetailsCtx, item: Document | None = None, out: ItemDetails | None = None): """ Determines item_tax template from item or parent item groups. @@ -821,7 +833,7 @@ def is_within_valid_range(ctx: ItemDetailsCtx, tax) -> bool: @frappe.whitelist() -def get_item_tax_map(*, doc: str | dict | Document, tax_template: str | None = None, as_json=True): +def get_item_tax_map(*, doc: str | dict | Document, tax_template: str | None = None, as_json: bool = True): doc = parse_json(doc) item_tax_map = {} for t in (t for t in (doc.get("taxes") or []) if not t.get("set_by_item_tax_template")): @@ -838,7 +850,7 @@ def get_item_tax_map(*, doc: str | dict | Document, tax_template: str | None = N @frappe.whitelist() @erpnext.normalize_ctx_input(ItemDetailsCtx) -def calculate_service_end_date(ctx: ItemDetailsCtx, item=None): +def calculate_service_end_date(ctx: ItemDetailsCtx, item: Document | None = None): _preprocess_ctx(ctx) if not item: item = frappe.get_cached_doc("Item", ctx.item_code) @@ -1156,7 +1168,7 @@ def get_item_price( @frappe.whitelist() -def get_batch_based_item_price(pctx: ItemPriceCtx | dict | str, item_code) -> float: +def get_batch_based_item_price(pctx: ItemPriceCtx | dict | str, item_code: str): pctx = parse_json(pctx) item_price = get_item_price(pctx, item_code, force_batch_no=True) @@ -1172,7 +1184,7 @@ def get_batch_based_item_price(pctx: ItemPriceCtx | dict | str, item_code) -> fl @erpnext.normalize_ctx_input(ItemDetailsCtx) -def get_price_list_rate_for(ctx: ItemDetailsCtx, item_code): +def get_price_list_rate_for(ctx: ItemDetailsCtx, item_code: str): """ :param customer: link to Customer DocType :param supplier: link to Supplier DocType @@ -1355,7 +1367,7 @@ def get_pos_profile_item_details_(ctx: ItemDetailsCtx, company, pos_profile=None @frappe.whitelist() -def get_pos_profile(company, pos_profile=None, user=None): +def get_pos_profile(company: str, pos_profile: str | None = None, user: str | None = None): if pos_profile: return frappe.get_cached_doc("POS Profile", pos_profile) @@ -1391,7 +1403,7 @@ def get_pos_profile(company, pos_profile=None, user=None): @frappe.whitelist() -def get_conversion_factor(item_code, uom): +def get_conversion_factor(item_code: str | None, uom: str): item = frappe.get_cached_value("Item", item_code, ["variant_of", "stock_uom"], as_dict=True) if not item_code or not item or uom == item.stock_uom: return {"conversion_factor": 1.0} @@ -1422,7 +1434,7 @@ def get_conversion_factor(item_code, uom): @frappe.whitelist() -def get_projected_qty(item_code, warehouse): +def get_projected_qty(item_code: str, warehouse: str): return { "projected_qty": frappe.db.get_value( "Bin", {"item_code": item_code, "warehouse": warehouse}, "projected_qty" @@ -1431,7 +1443,9 @@ def get_projected_qty(item_code, warehouse): @frappe.whitelist() -def get_bin_details(item_code, warehouse, company=None, include_child_warehouses=False): +def get_bin_details( + item_code: str, warehouse: str | None, company: str | None = None, include_child_warehouses: bool = False +): bin_details = {"projected_qty": 0, "actual_qty": 0, "reserved_qty": 0} if warehouse: @@ -1472,7 +1486,7 @@ def get_company_total_stock(item_code, company): @frappe.whitelist() -def get_batch_qty(batch_no, warehouse, item_code): +def get_batch_qty(batch_no: str, warehouse: str, item_code: str): from erpnext.stock.doctype.batch import batch if batch_no: @@ -1481,7 +1495,7 @@ def get_batch_qty(batch_no, warehouse, item_code): @frappe.whitelist() @erpnext.normalize_ctx_input(ItemDetailsCtx) -def apply_price_list(ctx, as_doc=False, doc=None): +def apply_price_list(ctx: ItemDetailsCtx, as_doc: bool = False, doc: Document | None = None): """Apply pricelist on a document-like dict object and return as {'parent': dict, 'children': list} @@ -1581,7 +1595,7 @@ def get_price_list_currency_and_exchange_rate(ctx: ItemDetailsCtx): @frappe.whitelist() -def get_default_bom(item_code=None): +def get_default_bom(item_code: str | None = None): def _get_bom(item): bom = frappe.get_all("BOM", dict(item=item, is_active=True, is_default=True, docstatus=1), limit=1) return bom[0].name if bom else None @@ -1599,7 +1613,7 @@ def get_default_bom(item_code=None): @frappe.whitelist() -def get_valuation_rate(item_code, company, warehouse=None): +def get_valuation_rate(item_code: str, company: str, warehouse: str | None = None): if frappe.get_cached_value("Warehouse", warehouse, "is_group"): return {"valuation_rate": 0.0} @@ -1640,7 +1654,7 @@ def get_gross_profit(out: ItemDetails): @frappe.whitelist() -def get_serial_no(_args, serial_nos=None, sales_order=None): +def get_serial_no(_args: Any, serial_nos: list | None = None, sales_order: str | None = None): serial_nos = serial_nos or [] return serial_nos diff --git a/erpnext/stock/report/incorrect_serial_and_batch_bundle/incorrect_serial_and_batch_bundle.py b/erpnext/stock/report/incorrect_serial_and_batch_bundle/incorrect_serial_and_batch_bundle.py index 0b27d697a4d..e191da4ff73 100644 --- a/erpnext/stock/report/incorrect_serial_and_batch_bundle/incorrect_serial_and_batch_bundle.py +++ b/erpnext/stock/report/incorrect_serial_and_batch_bundle/incorrect_serial_and_batch_bundle.py @@ -134,7 +134,7 @@ def get_linked_cancelled_sabb(filters): @frappe.whitelist() -def fix_sabb_entries(selected_rows): +def fix_sabb_entries(selected_rows: str | list): if isinstance(selected_rows, str): selected_rows = frappe.parse_json(selected_rows) diff --git a/erpnext/stock/report/serial_and_batch_summary/serial_and_batch_summary.py b/erpnext/stock/report/serial_and_batch_summary/serial_and_batch_summary.py index 8d26e74a0f5..39e707d3b77 100644 --- a/erpnext/stock/report/serial_and_batch_summary/serial_and_batch_summary.py +++ b/erpnext/stock/report/serial_and_batch_summary/serial_and_batch_summary.py @@ -1,6 +1,8 @@ # Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt +from typing import Any + import frappe from frappe import _ @@ -179,7 +181,7 @@ def get_columns(filters, data): @frappe.whitelist() @frappe.validate_and_sanitize_search_inputs -def get_voucher_type(doctype, txt, searchfield, start, page_len, filters): +def get_voucher_type(doctype: Any, txt: str, searchfield: Any, start: int, page_len: int, filters: dict): child_doctypes = frappe.get_all( "DocField", filters={"fieldname": "serial_and_batch_bundle"}, @@ -196,7 +198,7 @@ def get_voucher_type(doctype, txt, searchfield, start, page_len, filters): @frappe.whitelist() @frappe.validate_and_sanitize_search_inputs -def get_serial_nos(doctype, txt, searchfield, start, page_len, filters): +def get_serial_nos(doctype: Any, txt: str, searchfield: Any, start: int, page_len: int, filters: dict): query_filters = {} if txt: @@ -224,7 +226,7 @@ def get_serial_nos(doctype, txt, searchfield, start, page_len, filters): @frappe.whitelist() @frappe.validate_and_sanitize_search_inputs -def get_batch_nos(doctype, txt, searchfield, start, page_len, filters): +def get_batch_nos(doctype: Any, txt: str, searchfield: Any, start: int, page_len: int, filters: dict): query_filters = {} if filters.get("voucher_no") and txt: diff --git a/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py b/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py index 8afe1d72e27..d3654606613 100644 --- a/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py +++ b/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py @@ -174,7 +174,7 @@ def get_columns(filters): @frappe.whitelist() -def create_reposting_entries(rows, company): +def create_reposting_entries(rows: str | list, company: str): if isinstance(rows, str): rows = parse_json(rows) diff --git a/erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.py b/erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.py index 954acf998d8..edfcde2de2c 100644 --- a/erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.py +++ b/erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.py @@ -296,7 +296,7 @@ def get_columns(): @frappe.whitelist() -def create_reposting_entries(rows, item_code=None, warehouse=None): +def create_reposting_entries(rows: str | list, item_code: str | None = None, warehouse: str | None = None): if isinstance(rows, str): rows = parse_json(rows) diff --git a/erpnext/stock/report/stock_qty_vs_batch_qty/stock_qty_vs_batch_qty.py b/erpnext/stock/report/stock_qty_vs_batch_qty/stock_qty_vs_batch_qty.py index 87c5e1419cc..df3dc62c27f 100644 --- a/erpnext/stock/report/stock_qty_vs_batch_qty/stock_qty_vs_batch_qty.py +++ b/erpnext/stock/report/stock_qty_vs_batch_qty/stock_qty_vs_batch_qty.py @@ -100,7 +100,7 @@ def get_data(filters=None): @frappe.whitelist() -def update_batch_qty(selected_batches=None): +def update_batch_qty(selected_batches: str | None = None): if not selected_batches: return diff --git a/erpnext/stock/utils.py b/erpnext/stock/utils.py index b4f25e22e04..3ec8f401741 100644 --- a/erpnext/stock/utils.py +++ b/erpnext/stock/utils.py @@ -2,12 +2,14 @@ # License: GNU General Public License v3. See license.txt +import datetime import json import frappe from frappe import _ from frappe.query_builder.functions import IfNull, Sum from frappe.utils import cstr, flt, get_link_to_form, get_time, getdate, nowdate, nowtime +from frappe.utils.data import DateTimeLikeObject import erpnext from erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle import get_available_serial_nos @@ -93,13 +95,13 @@ def get_stock_value_on( @frappe.whitelist() def get_stock_balance( - item_code, - warehouse, - posting_date=None, - posting_time=None, - with_valuation_rate=False, - with_serial_no=False, - inventory_dimensions_dict=None, + item_code: str, + warehouse: str, + posting_date: DateTimeLikeObject | None = None, + posting_time: DateTimeLikeObject | datetime.timedelta | None = None, + with_valuation_rate: bool = False, + with_serial_no: bool = False, + inventory_dimensions_dict: dict | None = None, ): """Returns stock balance quantity at given warehouse on given posting date or current date. @@ -165,7 +167,7 @@ def get_serial_nos_data(serial_nos): @frappe.whitelist() -def get_latest_stock_qty(item_code, warehouse=None): +def get_latest_stock_qty(item_code: str, warehouse: str | None = None): values, condition = [item_code], "" if warehouse: lft, rgt, is_group = frappe.db.get_value("Warehouse", warehouse, ["lft", "rgt", "is_group"]) @@ -237,7 +239,7 @@ def _create_bin(item_code, warehouse): @frappe.whitelist() -def get_incoming_rate(args, raise_error_if_no_rate=True, fallbacks: bool = True): +def get_incoming_rate(args: dict | str, raise_error_if_no_rate: bool = True, fallbacks: bool = True): """Get Incoming Rate based on valuation method""" from erpnext.stock.stock_ledger import get_previous_sle, get_valuation_rate