mirror of
https://github.com/frappe/erpnext.git
synced 2026-08-15 15:38:39 +00:00
Merge pull request #56702 from mihir-kandoi/fix/normalize-ctx-input-py314
fix: keep normalize_ctx_input's ctx annotation on Python 3.14
This commit is contained in:
@@ -179,7 +179,12 @@ def normalize_ctx_input(T: type) -> callable:
|
||||
|
||||
def decorator(func: callable):
|
||||
# conserve annotations for frappe.utils.typing_validations
|
||||
@functools.wraps(func, assigned=(a for a in functools.WRAPPER_ASSIGNMENTS if a != "__annotations__"))
|
||||
@functools.wraps(
|
||||
func,
|
||||
assigned=(
|
||||
a for a in functools.WRAPPER_ASSIGNMENTS if a not in ("__annotations__", "__annotate__")
|
||||
),
|
||||
)
|
||||
def wrapper(ctx: T | Document | dict | str, *args, **kwargs):
|
||||
if isinstance(ctx, Document):
|
||||
ctx = T(**ctx.as_dict())
|
||||
|
||||
@@ -663,7 +663,6 @@ class POSInvoice(SalesInvoice):
|
||||
def set_pos_fields(self, for_validate=False):
|
||||
"""Set retail related fields from POS Profiles"""
|
||||
from erpnext.stock.get_item_details import (
|
||||
ItemDetailsCtx,
|
||||
get_pos_profile,
|
||||
get_pos_profile_item_details_,
|
||||
)
|
||||
@@ -736,7 +735,7 @@ class POSInvoice(SalesInvoice):
|
||||
for item in self.get("items"):
|
||||
if item.get("item_code"):
|
||||
profile_details = get_pos_profile_item_details_(
|
||||
ItemDetailsCtx(item.as_dict()), profile.get("company"), profile
|
||||
frappe._dict(item.as_dict()), profile.get("company"), profile
|
||||
)
|
||||
for fname, val in profile_details.items():
|
||||
if (not for_validate) or (for_validate and not item.get(fname)):
|
||||
|
||||
@@ -126,13 +126,13 @@ class POSService:
|
||||
doc.update_stock = 0 if dn_flag else cint(pos.get("update_stock"))
|
||||
|
||||
def _apply_pos_item_defaults(self, pos, for_validate: bool) -> None:
|
||||
from erpnext.stock.get_item_details import ItemDetailsCtx, get_pos_profile_item_details_
|
||||
from erpnext.stock.get_item_details import get_pos_profile_item_details_
|
||||
|
||||
for item in self.doc.get("items"):
|
||||
if not item.get("item_code"):
|
||||
continue
|
||||
profile_details = get_pos_profile_item_details_(
|
||||
ItemDetailsCtx(item.as_dict()), pos, pos, update_data=True
|
||||
frappe._dict(item.as_dict()), pos, pos, update_data=True
|
||||
)
|
||||
for fname, val in profile_details.items():
|
||||
if (not for_validate) or (for_validate and not item.get(fname)):
|
||||
|
||||
@@ -12,7 +12,6 @@ from frappe.utils import cint, flt, parse_json
|
||||
import erpnext
|
||||
from erpnext.stock.get_item_details import (
|
||||
NOT_APPLICABLE_TAX,
|
||||
ItemDetailsCtx,
|
||||
_get_item_tax_template,
|
||||
_get_item_tax_template_from_item_group,
|
||||
get_item_tax_map,
|
||||
@@ -350,7 +349,7 @@ def set_balance_in_account_currency(
|
||||
|
||||
|
||||
def set_child_tax_template_and_map(item, child_item, parent_doc) -> None:
|
||||
ctx = ItemDetailsCtx(
|
||||
ctx = frappe._dict(
|
||||
{
|
||||
"item_code": item.item_code,
|
||||
"posting_date": parent_doc.transaction_date,
|
||||
|
||||
@@ -500,7 +500,7 @@ def get_target_item_details(item_code: str | None = None, company: str | None =
|
||||
item_group_defaults = get_item_group_defaults(item.name, company)
|
||||
brand_defaults = get_brand_defaults(item.name, company)
|
||||
out.cost_center = get_default_cost_center(
|
||||
ItemDetailsCtx({"item_code": item.name, "company": company}),
|
||||
frappe._dict({"item_code": item.name, "company": company}),
|
||||
item_defaults,
|
||||
item_group_defaults,
|
||||
brand_defaults,
|
||||
|
||||
@@ -1531,11 +1531,11 @@ class TestPurchaseOrder(ERPNextTestSuite):
|
||||
(via the standard item lookup the form uses) without going through
|
||||
the Sales Order → Purchase Order mapping pipeline.
|
||||
"""
|
||||
from erpnext.stock.get_item_details import ItemDetailsCtx, get_item_details
|
||||
from erpnext.stock.get_item_details import get_item_details
|
||||
|
||||
item = make_item("_Test Drop Ship From Master", {"is_stock_item": 1, "delivered_by_supplier": 1})
|
||||
|
||||
ctx = ItemDetailsCtx(
|
||||
ctx = frappe._dict(
|
||||
{
|
||||
"item_code": item.item_code,
|
||||
"doctype": "Purchase Order",
|
||||
|
||||
@@ -47,7 +47,6 @@ from erpnext.controllers.sales_and_purchase_return import validate_return
|
||||
from erpnext.setup.utils import get_exchange_rate
|
||||
from erpnext.stock.doctype.item.item import get_uom_conv_factor
|
||||
from erpnext.stock.get_item_details import (
|
||||
ItemDetailsCtx,
|
||||
get_item_details,
|
||||
)
|
||||
from erpnext.utilities.regional import temporary_flag
|
||||
@@ -782,7 +781,7 @@ class AccountsController(TransactionBase):
|
||||
|
||||
for item in self.get("items"):
|
||||
if item.get("item_code"):
|
||||
ctx: ItemDetailsCtx = ItemDetailsCtx(parent_dict.copy())
|
||||
ctx: frappe._dict = frappe._dict(parent_dict.copy())
|
||||
ctx.update(item.as_dict())
|
||||
|
||||
ctx.update(
|
||||
|
||||
@@ -25,7 +25,7 @@ from pypika import Order
|
||||
|
||||
import erpnext
|
||||
from erpnext.accounts.utils import build_qb_match_conditions
|
||||
from erpnext.stock.get_item_details import ItemDetailsCtx, _get_item_tax_template
|
||||
from erpnext.stock.get_item_details import _get_item_tax_template
|
||||
from erpnext.stock.utils import get_combine_datetime
|
||||
from erpnext.utilities.query import get_filter_conditions_qb
|
||||
|
||||
@@ -1056,7 +1056,7 @@ def get_tax_template(doctype: str, txt: str, searchfield: str, start: int, page_
|
||||
valid_from = filters.get("valid_from")
|
||||
valid_from = valid_from[1] if isinstance(valid_from, list) else valid_from
|
||||
|
||||
ctx = ItemDetailsCtx(
|
||||
ctx = frappe._dict(
|
||||
{
|
||||
"item_code": filters.get("item_code"),
|
||||
"posting_date": valid_from,
|
||||
|
||||
@@ -21,7 +21,6 @@ from erpnext.controllers.accounts_controller import (
|
||||
from erpnext.deprecation_dumpster import deprecated
|
||||
from erpnext.stock.get_item_details import (
|
||||
NOT_APPLICABLE_TAX,
|
||||
ItemDetailsCtx,
|
||||
_get_item_tax_template,
|
||||
get_item_tax_map,
|
||||
)
|
||||
@@ -99,7 +98,7 @@ class calculate_taxes_and_totals:
|
||||
for item in self.doc.items:
|
||||
if item.item_code and item.get("item_tax_template"):
|
||||
item_doc = frappe.get_cached_doc("Item", item.item_code)
|
||||
ctx = ItemDetailsCtx(
|
||||
ctx = frappe._dict(
|
||||
{
|
||||
"net_rate": item.net_rate or item.rate,
|
||||
"base_net_rate": item.base_net_rate or item.base_rate,
|
||||
|
||||
@@ -16,7 +16,7 @@ from frappe.website.website_generator import WebsiteGenerator
|
||||
import erpnext
|
||||
from erpnext.setup.utils import get_exchange_rate
|
||||
from erpnext.stock.doctype.item.item import get_item_details
|
||||
from erpnext.stock.get_item_details import ItemDetailsCtx, get_conversion_factor, get_price_list_rate
|
||||
from erpnext.stock.get_item_details import get_conversion_factor, get_price_list_rate
|
||||
|
||||
form_grid_templates = {"items": "templates/form_grid/item_grid.html"}
|
||||
|
||||
@@ -1072,7 +1072,7 @@ def _get_price_list_item_rate(args, bom_doc):
|
||||
if not bom_doc.buying_price_list:
|
||||
frappe.throw(_("Please select Price List"))
|
||||
|
||||
ctx = ItemDetailsCtx(
|
||||
ctx = frappe._dict(
|
||||
{
|
||||
"doctype": "BOM",
|
||||
"price_list": bom_doc.buying_price_list,
|
||||
|
||||
@@ -2132,7 +2132,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
|
||||
frappe.call({
|
||||
method: "erpnext.stock.get_item_details.get_batch_based_item_price",
|
||||
args: {
|
||||
pctx: params,
|
||||
ctx: params,
|
||||
item_code: row.item_code,
|
||||
},
|
||||
callback: function (r) {
|
||||
|
||||
@@ -290,7 +290,7 @@ class TestQuotation(ERPNextTestSuite):
|
||||
def test_gross_profit(self):
|
||||
from erpnext.stock.doctype.item.test_item import make_item
|
||||
from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
|
||||
from erpnext.stock.get_item_details import ItemDetailsCtx, insert_item_price
|
||||
from erpnext.stock.get_item_details import insert_item_price
|
||||
|
||||
item_doc = make_item("_Test Item for Gross Profit", {"is_stock_item": 1})
|
||||
item_code = item_doc.name
|
||||
@@ -299,7 +299,7 @@ class TestQuotation(ERPNextTestSuite):
|
||||
selling_price_list = frappe.get_all("Price List", filters={"selling": 1}, limit=1)[0].name
|
||||
frappe.db.set_single_value("Stock Settings", "auto_insert_price_list_rate_if_missing", 1)
|
||||
insert_item_price(
|
||||
ItemDetailsCtx(
|
||||
frappe._dict(
|
||||
{
|
||||
"item_code": item_code,
|
||||
"price_list": selling_price_list,
|
||||
|
||||
@@ -26,7 +26,7 @@ from erpnext.stock.doctype.stock_reservation_entry.stock_reservation_entry impor
|
||||
get_sre_reserved_qty_details_for_voucher,
|
||||
get_ssb_bundle_for_voucher,
|
||||
)
|
||||
from erpnext.stock.get_item_details import ItemDetailsCtx, get_bin_details, get_price_list_rate
|
||||
from erpnext.stock.get_item_details import get_bin_details, get_price_list_rate
|
||||
|
||||
|
||||
def get_requested_item_qty(sales_order: str) -> dict:
|
||||
@@ -105,7 +105,7 @@ def make_material_request(source_name: str, target_doc: str | Document | None =
|
||||
target.item_code, target.warehouse, source_parent.company, True
|
||||
).get("actual_qty", 0)
|
||||
|
||||
ctx = ItemDetailsCtx(target.as_dict().copy())
|
||||
ctx = frappe._dict(target.as_dict().copy())
|
||||
ctx.update(
|
||||
{
|
||||
"company": source_parent.get("company"),
|
||||
|
||||
@@ -19,7 +19,7 @@ from erpnext.stock.doctype.serial_and_batch_bundle.test_serial_and_batch_bundle
|
||||
get_batch_from_bundle,
|
||||
)
|
||||
from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
|
||||
from erpnext.stock.get_item_details import ItemDetailsCtx, get_item_details
|
||||
from erpnext.stock.get_item_details import get_item_details
|
||||
from erpnext.stock.serial_batch_bundle import SerialBatchCreation
|
||||
from erpnext.tests.utils import ERPNextTestSuite
|
||||
|
||||
@@ -595,7 +595,7 @@ class TestBatch(ERPNextTestSuite):
|
||||
company = "_Test Company with perpetual inventory"
|
||||
currency = frappe.get_cached_value("Company", company, "default_currency")
|
||||
|
||||
ctx = ItemDetailsCtx(
|
||||
ctx = frappe._dict(
|
||||
{
|
||||
"item_code": "_Test Batch Price Item",
|
||||
"company": company,
|
||||
|
||||
@@ -25,7 +25,7 @@ from erpnext.stock.doctype.item.item import (
|
||||
validate_is_stock_item,
|
||||
)
|
||||
from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
|
||||
from erpnext.stock.get_item_details import ItemDetailsCtx, get_item_details
|
||||
from erpnext.stock.get_item_details import get_item_details
|
||||
from erpnext.tests.utils import ERPNextTestSuite
|
||||
|
||||
|
||||
@@ -158,7 +158,7 @@ class TestItem(ERPNextTestSuite):
|
||||
currency = frappe.get_cached_value("Company", company, "default_currency")
|
||||
|
||||
details = get_item_details(
|
||||
ItemDetailsCtx(
|
||||
frappe._dict(
|
||||
{
|
||||
"item_code": "_Test Item",
|
||||
"company": company,
|
||||
@@ -188,7 +188,7 @@ class TestItem(ERPNextTestSuite):
|
||||
create_fixed_asset_item()
|
||||
|
||||
details = get_item_details(
|
||||
ItemDetailsCtx(
|
||||
frappe._dict(
|
||||
{
|
||||
"item_code": "Macbook Pro",
|
||||
"company": "_Test Company",
|
||||
@@ -201,7 +201,7 @@ class TestItem(ERPNextTestSuite):
|
||||
|
||||
frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", "1")
|
||||
details = get_item_details(
|
||||
ItemDetailsCtx(
|
||||
frappe._dict(
|
||||
{
|
||||
"item_code": "Macbook Pro",
|
||||
"company": "_Test Company",
|
||||
@@ -291,7 +291,7 @@ class TestItem(ERPNextTestSuite):
|
||||
|
||||
for data in expected_item_tax_template:
|
||||
details = get_item_details(
|
||||
ItemDetailsCtx(
|
||||
frappe._dict(
|
||||
{
|
||||
"item_code": data["item_code"],
|
||||
"tax_category": data["tax_category"],
|
||||
@@ -343,7 +343,7 @@ class TestItem(ERPNextTestSuite):
|
||||
"cost_center": "_Test Cost Center 2 - _TC", # from item group
|
||||
}
|
||||
sales_item_details = get_item_details(
|
||||
ItemDetailsCtx(
|
||||
frappe._dict(
|
||||
{
|
||||
"item_code": "Test Item With Defaults",
|
||||
"company": "_Test Company",
|
||||
@@ -368,7 +368,7 @@ class TestItem(ERPNextTestSuite):
|
||||
"cost_center": "_Test Write Off Cost Center - _TC", # from item
|
||||
}
|
||||
purchase_item_details = get_item_details(
|
||||
ItemDetailsCtx(
|
||||
frappe._dict(
|
||||
{
|
||||
"item_code": "Test Item With Defaults",
|
||||
"company": "_Test Company",
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import frappe
|
||||
|
||||
from erpnext.stock.doctype.item_price.item_price import ItemPriceDuplicateItem
|
||||
from erpnext.stock.get_item_details import ItemDetailsCtx, get_price_list_rate_for
|
||||
from erpnext.stock.get_item_details import get_price_list_rate_for
|
||||
from erpnext.tests.utils import ERPNextTestSuite
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ class TestItemPrice(ERPNextTestSuite):
|
||||
# Check correct price at this quantity
|
||||
doc = frappe.copy_doc(self.globalTestRecords["Item Price"][2])
|
||||
|
||||
ctx = ItemDetailsCtx(
|
||||
ctx = frappe._dict(
|
||||
{
|
||||
"price_list": doc.price_list,
|
||||
"customer": doc.customer,
|
||||
@@ -84,7 +84,7 @@ class TestItemPrice(ERPNextTestSuite):
|
||||
def test_price_with_no_qty(self):
|
||||
# Check correct price when no quantity
|
||||
doc = frappe.copy_doc(self.globalTestRecords["Item Price"][2])
|
||||
ctx = ItemDetailsCtx(
|
||||
ctx = frappe._dict(
|
||||
{
|
||||
"price_list": doc.price_list,
|
||||
"customer": doc.customer,
|
||||
@@ -100,7 +100,7 @@ class TestItemPrice(ERPNextTestSuite):
|
||||
# Check correct price at first date
|
||||
doc = frappe.copy_doc(self.globalTestRecords["Item Price"][2])
|
||||
|
||||
ctx = ItemDetailsCtx(
|
||||
ctx = frappe._dict(
|
||||
{
|
||||
"price_list": doc.price_list,
|
||||
"customer": "_Test Customer",
|
||||
@@ -117,7 +117,7 @@ class TestItemPrice(ERPNextTestSuite):
|
||||
# Check correct price at invalid date
|
||||
doc = frappe.copy_doc(self.globalTestRecords["Item Price"][3])
|
||||
|
||||
ctx = ItemDetailsCtx(
|
||||
ctx = frappe._dict(
|
||||
{
|
||||
"price_list": doc.price_list,
|
||||
"qty": 7,
|
||||
@@ -133,7 +133,7 @@ class TestItemPrice(ERPNextTestSuite):
|
||||
# Check correct price when outside of the date
|
||||
doc = frappe.copy_doc(self.globalTestRecords["Item Price"][4])
|
||||
|
||||
ctx = ItemDetailsCtx(
|
||||
ctx = frappe._dict(
|
||||
{
|
||||
"price_list": doc.price_list,
|
||||
"customer": "_Test Customer",
|
||||
@@ -150,7 +150,7 @@ class TestItemPrice(ERPNextTestSuite):
|
||||
# Check lowest price when no date provided
|
||||
doc = frappe.copy_doc(self.globalTestRecords["Item Price"][1])
|
||||
|
||||
ctx = ItemDetailsCtx(
|
||||
ctx = frappe._dict(
|
||||
{
|
||||
"price_list": doc.price_list,
|
||||
"uom": "_Test UOM",
|
||||
@@ -182,7 +182,7 @@ class TestItemPrice(ERPNextTestSuite):
|
||||
doc.price_list_rate = 21
|
||||
doc.insert()
|
||||
|
||||
ctx = ItemDetailsCtx(
|
||||
ctx = frappe._dict(
|
||||
{
|
||||
"price_list": doc.price_list,
|
||||
"uom": "_Test UOM",
|
||||
|
||||
@@ -12,7 +12,7 @@ from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import flt
|
||||
|
||||
from erpnext.stock.get_item_details import ItemDetailsCtx, get_item_details, get_price_list_rate
|
||||
from erpnext.stock.get_item_details import get_item_details, get_price_list_rate
|
||||
|
||||
|
||||
class PackedItem(Document):
|
||||
@@ -344,7 +344,7 @@ def update_packed_item_price_data(pi_row, item_data, doc):
|
||||
return
|
||||
|
||||
item_doc = frappe.get_cached_doc("Item", pi_row.item_code)
|
||||
ctx = ItemDetailsCtx(pi_row.as_dict().copy())
|
||||
ctx = frappe._dict(pi_row.as_dict().copy())
|
||||
ctx.update(
|
||||
{
|
||||
"company": doc.get("company"),
|
||||
@@ -442,7 +442,7 @@ def get_items_from_product_bundle(row: str | dict):
|
||||
"""
|
||||
from erpnext.selling.doctype.product_bundle.product_bundle import get_active_product_bundle
|
||||
|
||||
row, items = ItemDetailsCtx(frappe.parse_json(row)), []
|
||||
row, items = frappe._dict(frappe.parse_json(row)), []
|
||||
|
||||
if bundle_name := row.get("product_bundle"):
|
||||
frappe.has_permission("Product Bundle", "read", bundle_name, throw=True)
|
||||
|
||||
@@ -2148,7 +2148,7 @@ class TestPurchaseReceipt(ERPNextTestSuite):
|
||||
self.assertEqual(return_pi.docstatus, 1)
|
||||
|
||||
def test_disable_last_purchase_rate(self):
|
||||
from erpnext.stock.get_item_details import ItemDetailsCtx, get_item_details
|
||||
from erpnext.stock.get_item_details import get_item_details
|
||||
|
||||
item = make_item(
|
||||
"_Test Disable Last Purchase Rate",
|
||||
@@ -2163,7 +2163,7 @@ class TestPurchaseReceipt(ERPNextTestSuite):
|
||||
item_code=item.name,
|
||||
)
|
||||
|
||||
ctx = ItemDetailsCtx(pr.items[0].as_dict())
|
||||
ctx = frappe._dict(pr.items[0].as_dict())
|
||||
ctx.update(
|
||||
{
|
||||
"supplier": pr.supplier,
|
||||
|
||||
@@ -28,7 +28,6 @@ from erpnext.manufacturing.doctype.bom.bom import (
|
||||
from erpnext.setup.doctype.brand.brand import get_brand_defaults
|
||||
from erpnext.setup.doctype.item_group.item_group import get_item_group_defaults
|
||||
from erpnext.stock.get_item_details import (
|
||||
ItemDetailsCtx,
|
||||
get_barcode_data,
|
||||
get_bin_details,
|
||||
get_conversion_factor,
|
||||
@@ -1189,7 +1188,7 @@ class StockEntry(StockController, SubcontractingInwardController):
|
||||
return reserved_work_orders
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_item_details(self, args: ItemDetailsCtx | None = None, for_update: bool = False):
|
||||
def get_item_details(self, args: frappe._dict | None = None, for_update: bool = False):
|
||||
item = self._fetch_item_data(args)
|
||||
item_group_defaults = get_item_group_defaults(item.name, self.company)
|
||||
brand_defaults = get_brand_defaults(item.name, self.company)
|
||||
|
||||
@@ -27,9 +27,7 @@ from erpnext.stock.doctype.item.item import get_item_defaults, get_uom_conv_fact
|
||||
from erpnext.stock.doctype.item_manufacturer.item_manufacturer import get_item_manufacturer_part_no
|
||||
from erpnext.stock.doctype.price_list.price_list import get_price_list_details
|
||||
|
||||
ItemDetails = frappe._dict
|
||||
ItemDetailsCtx = frappe._dict
|
||||
ItemPriceCtx = frappe._dict
|
||||
|
||||
sales_doctypes = ["Quotation", "Sales Order", "Delivery Note", "Sales Invoice", "POS Invoice"]
|
||||
purchase_doctypes = [
|
||||
@@ -58,7 +56,7 @@ def _preprocess_ctx(ctx):
|
||||
@frappe.whitelist()
|
||||
@erpnext.normalize_ctx_input(ItemDetailsCtx)
|
||||
def get_item_details(
|
||||
ctx: ItemDetailsCtx | str,
|
||||
ctx: ItemDetailsCtx,
|
||||
doc: Document | str | None = None,
|
||||
for_validate: bool | None = False,
|
||||
overwrite_warehouse: bool = True,
|
||||
@@ -98,7 +96,7 @@ def get_item_details(
|
||||
if doc.get("doctype") == "Purchase Invoice":
|
||||
ctx.bill_date = doc.get("bill_date")
|
||||
|
||||
out: ItemDetails = get_basic_details(ctx, item, overwrite_warehouse)
|
||||
out: frappe._dict = get_basic_details(ctx, item, overwrite_warehouse)
|
||||
|
||||
get_item_tax_template(ctx, item, out)
|
||||
out.item_tax_rate = get_item_tax_map(
|
||||
@@ -184,13 +182,13 @@ def get_item_details(
|
||||
return out
|
||||
|
||||
|
||||
def remove_standard_fields(out: ItemDetails):
|
||||
def remove_standard_fields(out: frappe._dict):
|
||||
for key in child_table_fields + default_fields:
|
||||
out.pop(key, None)
|
||||
return out
|
||||
|
||||
|
||||
def set_valuation_rate(out: ItemDetails | dict, ctx: ItemDetailsCtx):
|
||||
def set_valuation_rate(out: frappe._dict, ctx: frappe._dict):
|
||||
from erpnext.selling.doctype.product_bundle.product_bundle import get_active_product_bundle
|
||||
|
||||
active_bundle = get_active_product_bundle(ctx.item_code)
|
||||
@@ -320,7 +318,7 @@ def get_filtered_serial_nos(serial_nos, doc, table=None):
|
||||
return serial_nos
|
||||
|
||||
|
||||
def update_bin_details(ctx: ItemDetailsCtx, out: ItemDetails, doc):
|
||||
def update_bin_details(ctx: frappe._dict, out: frappe._dict, doc):
|
||||
if ctx.doctype == "Material Request" and ctx.material_request_type == "Material Transfer":
|
||||
out.update(get_bin_details(ctx.item_code, ctx.from_warehouse))
|
||||
|
||||
@@ -346,7 +344,7 @@ def get_item_code(barcode=None, serial_no=None):
|
||||
return item_code
|
||||
|
||||
|
||||
def validate_item_details(ctx: ItemDetailsCtx, item):
|
||||
def validate_item_details(ctx: frappe._dict, item):
|
||||
if not ctx.company:
|
||||
throw(_("Please specify Company"))
|
||||
|
||||
@@ -365,7 +363,7 @@ def validate_item_details(ctx: ItemDetailsCtx, item):
|
||||
throw(_("Item {0} must be a Non-Stock Item").format(item.name))
|
||||
|
||||
|
||||
def get_basic_details(ctx: ItemDetailsCtx, item, overwrite_warehouse=True) -> ItemDetails:
|
||||
def get_basic_details(ctx: frappe._dict, item, overwrite_warehouse=True) -> frappe._dict:
|
||||
"""
|
||||
:param ctx: {
|
||||
"item_code": "",
|
||||
@@ -491,7 +489,7 @@ def get_basic_details(ctx: ItemDetailsCtx, item, overwrite_warehouse=True) -> It
|
||||
if ctx.batch_no and item.name != frappe.get_cached_value("Batch", ctx.batch_no, "item"):
|
||||
ctx.batch_no = ""
|
||||
|
||||
out = ItemDetails(
|
||||
out = frappe._dict(
|
||||
{
|
||||
"item_code": item.name,
|
||||
"item_name": item.item_name,
|
||||
@@ -721,9 +719,9 @@ def get_item_tax_info(
|
||||
if not item_code or item_code[1] in out or not item_tax_templates.get(item_code[1]):
|
||||
continue
|
||||
|
||||
out[item_code[1]] = ItemDetails()
|
||||
out[item_code[1]] = frappe._dict()
|
||||
item = frappe.get_cached_doc("Item", item_code[0])
|
||||
ctx: ItemDetailsCtx = {
|
||||
ctx: frappe._dict = {
|
||||
"company": doc.company,
|
||||
"tax_category": tax_category,
|
||||
"base_net_rate": item_rates.get(item_code[1]),
|
||||
@@ -744,9 +742,7 @@ def get_item_tax_info(
|
||||
|
||||
@frappe.whitelist()
|
||||
@erpnext.normalize_ctx_input(ItemDetailsCtx)
|
||||
def get_item_tax_template(
|
||||
ctx: ItemDetailsCtx | str, item: Document | None = None, out: ItemDetails | None = None
|
||||
):
|
||||
def get_item_tax_template(ctx: ItemDetailsCtx, item: Document | None = None, out: frappe._dict | None = None):
|
||||
"""
|
||||
Determines item_tax template from item or parent item groups.
|
||||
|
||||
@@ -797,7 +793,7 @@ def _get_item_tax_template_from_item_group(ctx, item_group, out=None):
|
||||
|
||||
@erpnext.normalize_ctx_input(ItemDetailsCtx)
|
||||
def _get_item_tax_template(
|
||||
ctx: ItemDetailsCtx, taxes, out: ItemDetails | None = None, for_validate=False
|
||||
ctx: ItemDetailsCtx, taxes, out: frappe._dict | None = None, for_validate=False
|
||||
) -> None | str | list[str]:
|
||||
"""
|
||||
Accesses:
|
||||
@@ -814,7 +810,7 @@ def _get_item_tax_template(
|
||||
}
|
||||
"""
|
||||
if out is None:
|
||||
out = ItemDetails()
|
||||
out = frappe._dict()
|
||||
taxes_with_validity = []
|
||||
taxes_with_no_validity = []
|
||||
|
||||
@@ -929,7 +925,7 @@ def calculate_service_end_date(ctx: ItemDetailsCtx, item: Document | None = None
|
||||
return deferred_detail
|
||||
|
||||
|
||||
def get_default_income_account(ctx: ItemDetailsCtx, item, item_group, brand):
|
||||
def get_default_income_account(ctx: frappe._dict, item, item_group, brand):
|
||||
return (
|
||||
item.get("income_account")
|
||||
or item_group.get("income_account")
|
||||
@@ -938,7 +934,7 @@ def get_default_income_account(ctx: ItemDetailsCtx, item, item_group, brand):
|
||||
)
|
||||
|
||||
|
||||
def get_default_inventory_account(ctx: ItemDetailsCtx, item, item_group, brand):
|
||||
def get_default_inventory_account(ctx: frappe._dict, item, item_group, brand):
|
||||
if not frappe.get_cached_value("Company", ctx.company, "enable_item_wise_inventory_account"):
|
||||
return None
|
||||
|
||||
@@ -950,7 +946,7 @@ def get_default_inventory_account(ctx: ItemDetailsCtx, item, item_group, brand):
|
||||
)
|
||||
|
||||
|
||||
def get_default_expense_account(ctx: ItemDetailsCtx, item, item_group, brand):
|
||||
def get_default_expense_account(ctx: frappe._dict, item, item_group, brand):
|
||||
if ctx.get("doctype") in ["Sales Invoice", "Delivery Note"]:
|
||||
expense_account = (
|
||||
item.get("default_cogs_account")
|
||||
@@ -972,7 +968,7 @@ def get_default_expense_account(ctx: ItemDetailsCtx, item, item_group, brand):
|
||||
)
|
||||
|
||||
|
||||
def get_provisional_account(ctx: ItemDetailsCtx, item, item_group, brand):
|
||||
def get_provisional_account(ctx: frappe._dict, item, item_group, brand):
|
||||
return (
|
||||
item.get("default_provisional_account")
|
||||
or item_group.get("default_provisional_account")
|
||||
@@ -981,7 +977,7 @@ def get_provisional_account(ctx: ItemDetailsCtx, item, item_group, brand):
|
||||
)
|
||||
|
||||
|
||||
def get_default_discount_account(ctx: ItemDetailsCtx, item, item_group, brand):
|
||||
def get_default_discount_account(ctx: frappe._dict, item, item_group, brand):
|
||||
return (
|
||||
item.get("default_discount_account")
|
||||
or item_group.get("default_discount_account")
|
||||
@@ -990,7 +986,7 @@ def get_default_discount_account(ctx: ItemDetailsCtx, item, item_group, brand):
|
||||
)
|
||||
|
||||
|
||||
def get_default_deferred_account(ctx: ItemDetailsCtx, item, fieldname=None):
|
||||
def get_default_deferred_account(ctx: frappe._dict, item, fieldname=None):
|
||||
if item.get("enable_deferred_revenue") or item.get("enable_deferred_expense"):
|
||||
return (
|
||||
frappe.get_cached_value(
|
||||
@@ -1055,13 +1051,13 @@ def get_default_cost_center(ctx: ItemDetailsCtx, item=None, item_group=None, bra
|
||||
return cost_center
|
||||
|
||||
|
||||
def get_default_supplier(_ctx: ItemDetailsCtx, item, item_group, brand):
|
||||
def get_default_supplier(_ctx: frappe._dict, item, item_group, brand):
|
||||
return item.get("default_supplier") or item_group.get("default_supplier") or brand.get("default_supplier")
|
||||
|
||||
|
||||
def get_price_list_rate(ctx: ItemDetailsCtx, item_doc, out: ItemDetails = None):
|
||||
def get_price_list_rate(ctx: frappe._dict, item_doc, out: frappe._dict = None):
|
||||
if out is None:
|
||||
out = ItemDetails()
|
||||
out = frappe._dict()
|
||||
|
||||
meta = frappe.get_meta(ctx.parenttype or ctx.doctype)
|
||||
|
||||
@@ -1103,7 +1099,7 @@ def get_price_list_rate(ctx: ItemDetailsCtx, item_doc, out: ItemDetails = None):
|
||||
return out
|
||||
|
||||
|
||||
def insert_item_price(ctx: ItemDetailsCtx):
|
||||
def insert_item_price(ctx: frappe._dict):
|
||||
"""Insert Item Price if Price List and Price List Rate are specified and currency is the same"""
|
||||
if not ctx.price_list or not ctx.rate or ctx.is_internal_supplier or ctx.is_internal_customer:
|
||||
return
|
||||
@@ -1212,13 +1208,11 @@ def insert_item_price(ctx: ItemDetailsCtx):
|
||||
)
|
||||
|
||||
|
||||
def _get_stock_uom_rate(rate: float, ctx: ItemDetailsCtx):
|
||||
def _get_stock_uom_rate(rate: float, ctx: frappe._dict):
|
||||
return rate / ctx.conversion_factor if ctx.conversion_factor else rate
|
||||
|
||||
|
||||
def get_item_price(
|
||||
pctx: ItemPriceCtx | dict, item_code, ignore_party=False, force_batch_no=False
|
||||
) -> list[dict]:
|
||||
def get_item_price(pctx: frappe._dict, item_code, ignore_party=False, force_batch_no=False) -> list[dict]:
|
||||
"""
|
||||
Get name, price_list_rate from Item Price based on conditions
|
||||
Check if the desired qty is within the increment of the packing list.
|
||||
@@ -1226,7 +1220,7 @@ def get_item_price(
|
||||
optional fields transaction_date, customer, supplier
|
||||
:param item_code: str, Item Doctype field item_code
|
||||
"""
|
||||
pctx: ItemPriceCtx = frappe._dict(pctx)
|
||||
pctx: frappe._dict = frappe._dict(pctx)
|
||||
|
||||
ip = frappe.qb.DocType("Item Price")
|
||||
query = (
|
||||
@@ -1277,16 +1271,15 @@ def get_item_price(
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
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)
|
||||
@erpnext.normalize_ctx_input(ItemDetailsCtx)
|
||||
def get_batch_based_item_price(ctx: ItemDetailsCtx, item_code: str):
|
||||
item_price = get_item_price(ctx, item_code, force_batch_no=True)
|
||||
if not item_price:
|
||||
item_price = get_item_price(pctx, item_code, ignore_party=True, force_batch_no=True)
|
||||
item_price = get_item_price(ctx, item_code, ignore_party=True, force_batch_no=True)
|
||||
|
||||
is_free_item = pctx.get("items", [{}])[0].get("is_free_item")
|
||||
is_free_item = ctx.get("items", [{}])[0].get("is_free_item")
|
||||
|
||||
if item_price and item_price[0].uom == pctx.uom and not is_free_item:
|
||||
if item_price and item_price[0].uom == ctx.uom and not is_free_item:
|
||||
return item_price[0].price_list_rate
|
||||
|
||||
return 0.0
|
||||
@@ -1302,7 +1295,7 @@ def get_price_list_rate_for(ctx: ItemDetailsCtx, item_code: str):
|
||||
:param qty: Desired Qty
|
||||
:param transaction_date: Date of the price
|
||||
"""
|
||||
pctx = ItemPriceCtx(
|
||||
pctx = frappe._dict(
|
||||
{
|
||||
"item_code": item_code,
|
||||
"price_list": ctx.get("price_list"),
|
||||
@@ -1358,7 +1351,7 @@ def check_packing_list(price_list_rate_name, desired_qty, item_code):
|
||||
return flag
|
||||
|
||||
|
||||
def validate_conversion_rate(ctx: ItemDetailsCtx, meta):
|
||||
def validate_conversion_rate(ctx: frappe._dict, meta):
|
||||
from erpnext.controllers.accounts_controller import validate_conversion_rate
|
||||
|
||||
company_currency = frappe.get_cached_value("Company", ctx.company, "default_currency")
|
||||
@@ -1404,7 +1397,7 @@ def validate_conversion_rate(ctx: ItemDetailsCtx, meta):
|
||||
)
|
||||
|
||||
|
||||
def get_party_item_code(ctx: ItemDetailsCtx, item_doc, out: ItemDetails):
|
||||
def get_party_item_code(ctx: frappe._dict, item_doc, out: frappe._dict):
|
||||
if ctx.transaction_type == "selling" and ctx.customer:
|
||||
out.customer_item_code = None
|
||||
|
||||
@@ -1426,7 +1419,7 @@ def get_party_item_code(ctx: ItemDetailsCtx, item_doc, out: ItemDetails):
|
||||
out.supplier_part_no = item_supplier[0].supplier_part_no if item_supplier else None
|
||||
|
||||
|
||||
def get_tax_withholding_category(ctx: ItemDetailsCtx, item_doc, out: ItemDetails):
|
||||
def get_tax_withholding_category(ctx: frappe._dict, item_doc, out: frappe._dict):
|
||||
"""
|
||||
Get tax withholding category for the item based on the transaction type and party.
|
||||
"""
|
||||
@@ -1601,7 +1594,7 @@ def get_batch_qty(batch_no: str, warehouse: str, item_code: str):
|
||||
|
||||
@frappe.whitelist()
|
||||
@erpnext.normalize_ctx_input(ItemDetailsCtx)
|
||||
def apply_price_list(ctx: ItemDetailsCtx | str, as_doc: bool = False, doc: Document | str | None = None):
|
||||
def apply_price_list(ctx: ItemDetailsCtx, as_doc: bool = False, doc: Document | str | None = None):
|
||||
"""Apply pricelist on a document-like dict object and return as
|
||||
{'parent': dict, 'children': list}
|
||||
|
||||
@@ -1637,7 +1630,7 @@ def apply_price_list(ctx: ItemDetailsCtx | str, as_doc: bool = False, doc: Docum
|
||||
ctx.update(parent)
|
||||
|
||||
for item in item_list:
|
||||
ctx_copy = ItemDetailsCtx(ctx.copy())
|
||||
ctx_copy = frappe._dict(ctx.copy())
|
||||
ctx_copy.update(item)
|
||||
item_details = apply_price_list_on_item(ctx_copy, doc=doc)
|
||||
children.append(item_details)
|
||||
@@ -1665,7 +1658,7 @@ def apply_price_list_on_item(ctx, doc=None):
|
||||
return item_details
|
||||
|
||||
|
||||
def get_price_list_currency_and_exchange_rate(ctx: ItemDetailsCtx):
|
||||
def get_price_list_currency_and_exchange_rate(ctx: frappe._dict):
|
||||
if not ctx.price_list:
|
||||
return {}
|
||||
|
||||
@@ -1752,7 +1745,7 @@ def get_valuation_rate(item_code: str, company: str, warehouse: str | None = Non
|
||||
return {"valuation_rate": 0.0}
|
||||
|
||||
|
||||
def get_gross_profit(out: ItemDetails):
|
||||
def get_gross_profit(out: frappe._dict):
|
||||
if out.valuation_rate:
|
||||
out.update({"gross_profit": ((out.base_rate - out.valuation_rate) * out.stock_qty)})
|
||||
|
||||
@@ -1765,7 +1758,7 @@ def get_serial_no(_args: Any, serial_nos: list | None = None, sales_order: str |
|
||||
return serial_nos
|
||||
|
||||
|
||||
def update_party_blanket_order(ctx: ItemDetailsCtx, out: ItemDetails | dict):
|
||||
def update_party_blanket_order(ctx: frappe._dict, out: frappe._dict):
|
||||
if out["against_blanket_order"]:
|
||||
blanket_order_details = get_blanket_order_details(ctx)
|
||||
if blanket_order_details:
|
||||
|
||||
Reference in New Issue
Block a user