Esempio n. 1
0
def get_item_warehouse(item, args, overwrite_warehouse, defaults={}):
    if not defaults:
        defaults = frappe._dict({
            'item_defaults':
            get_item_defaults(item.name, args.company),
            'item_group_defaults':
            get_item_group_defaults(item.name, args.company),
            'brand_defaults':
            get_brand_defaults(item.name, args.company)
        })

    if overwrite_warehouse or not args.warehouse:
        warehouse = (args.get("set_warehouse")
                     or defaults.item_defaults.get("default_warehouse")
                     or defaults.item_group_defaults.get("default_warehouse")
                     or defaults.brand_defaults.get("default_warehouse")
                     or args.get('warehouse'))

        if not warehouse:
            defaults = frappe.defaults.get_defaults() or {}
            warehouse_exists = frappe.db.exists("Warehouse", {
                'name': defaults.default_warehouse,
                'company': args.company
            })
            if defaults.get("default_warehouse") and warehouse_exists:
                warehouse = defaults.default_warehouse

    else:
        warehouse = args.get('warehouse')

    return warehouse
Esempio n. 2
0
def get_item_warehouse(item, args, overwrite_warehouse, defaults=None):
	if not defaults:
		defaults = frappe._dict({
			'item_defaults' : get_item_defaults(item.name, args.company),
			'item_group_defaults' : get_item_group_defaults(item.name, args.company),
			'brand_defaults' : get_brand_defaults(item.name, args.company)
		})

	if overwrite_warehouse or not args.warehouse:
		warehouse = (
			args.get("set_warehouse") or
			defaults.item_defaults.get("default_warehouse") or
			defaults.item_group_defaults.get("default_warehouse") or
			defaults.brand_defaults.get("default_warehouse") or
			args.get('warehouse')
		)

		if not warehouse:
			defaults = frappe.defaults.get_defaults() or {}
			warehouse_exists = frappe.db.exists("Warehouse", {
				'name': defaults.default_warehouse,
				'company': args.company
			})
			if defaults.get("default_warehouse") and warehouse_exists:
				warehouse = defaults.default_warehouse

	else:
		warehouse = args.get('warehouse')

	if not warehouse:
		default_warehouse = frappe.db.get_single_value("Stock Settings", "default_warehouse")
		if frappe.db.get_value("Warehouse", default_warehouse, "company") == args.company:
			return default_warehouse

	return warehouse
Esempio n. 3
0
def get_valuation_rate(item_code, company, warehouse=None):
    item = get_item_defaults(item_code, company)
    item_group = get_item_group_defaults(item_code, company)
    brand = get_brand_defaults(item_code, company)
    # item = frappe.get_doc("Item", item_code)
    if item.get("is_stock_item"):
        if not warehouse:
            warehouse = item.get("default_warehouse") or item_group.get(
                "default_warehouse") or brand.get("default_warehouse")

        return frappe.db.get_value("Bin", {
            "item_code": item_code,
            "warehouse": warehouse
        }, ["valuation_rate"],
                                   as_dict=True) or {
                                       "valuation_rate": 0
                                   }

    elif not item.get("is_stock_item"):
        valuation_rate = frappe.db.sql(
            """select sum(base_net_amount) / sum(qty*conversion_factor)
			from `tabPurchase Invoice Item`
			where item_code = %s and docstatus=1""", item_code)

        if valuation_rate:
            return {"valuation_rate": valuation_rate[0][0] or 0.0}
    else:
        return {"valuation_rate": 0.0}
Esempio n. 4
0
def get_material_request_items(row, sales_order, company,
                               ignore_existing_ordered_qty, warehouse,
                               bin_dict):
    total_qty = row['qty']

    required_qty = 0
    if ignore_existing_ordered_qty or bin_dict.get("projected_qty", 0) < 0:
        required_qty = total_qty
    elif total_qty > bin_dict.get("projected_qty", 0):
        required_qty = total_qty - bin_dict.get("projected_qty", 0)
    if required_qty > 0 and required_qty < row['min_order_qty']:
        required_qty = row['min_order_qty']
    item_group_defaults = get_item_group_defaults(row.item_code, company)

    if not row['purchase_uom']:
        row['purchase_uom'] = row['stock_uom']

    if row['purchase_uom'] != row['stock_uom']:
        if not row['conversion_factor']:
            frappe.throw(
                _("UOM Conversion factor ({0} -> {1}) not found for item: {2}"
                  ).format(row['purchase_uom'], row['stock_uom'],
                           row.item_code))
        required_qty = required_qty / row['conversion_factor']

    if frappe.db.get_value("UOM", row['purchase_uom'], "must_be_whole_number"):
        required_qty = ceil(required_qty)

    if required_qty > 0:
        return {
            'item_code':
            row.item_code,
            'item_name':
            row.item_name,
            'quantity':
            required_qty,
            'description':
            row.description,
            'stock_uom':
            row.get("stock_uom"),
            'warehouse':
            warehouse or row.get('source_warehouse')
            or row.get('default_warehouse')
            or item_group_defaults.get("default_warehouse"),
            'actual_qty':
            bin_dict.get("actual_qty", 0),
            'projected_qty':
            bin_dict.get("projected_qty", 0),
            'min_order_qty':
            row['min_order_qty'],
            'material_request_type':
            row.get("default_material_request_type"),
            'sales_order':
            sales_order,
            'description':
            row.get("description"),
            'uom':
            row.get("purchase_uom") or row.get("stock_uom")
        }
def get_item_default_expense_account(item_code):
	item_defaults = get_item_defaults(item_code, frappe.db.get_single_value("Global Defaults", "default_company"))
	item_group_defaults = get_item_group_defaults(item_code, frappe.db.get_single_value("Global Defaults", "default_company"))
	expense_account = get_asset_category_account(fieldname = "fixed_asset_account", item = item_code, company= frappe.db.get_single_value("Global Defaults", "default_company"))
	if not expense_account:
		expense_account = item_defaults.get("expense_account") or item_group_defaults.get("expense_account") or get_brand_defaults(item_code,frappe.db.get_single_value("Global Defaults", "default_company") )
	frappe.response["expense_account"] = expense_account
	frappe.response["company"]= frappe.db.get_single_value("Global Defaults", "default_company")
	def update_item(obj, target, source_parent):
		target.amount = flt(obj.amount) - flt(obj.billed_amt)
		target.base_amount = target.amount * flt(source_parent.conversion_rate)
		target.qty = target.amount / flt(obj.rate) if (flt(obj.rate) and flt(obj.billed_amt)) else flt(obj.qty)

		item = get_item_defaults(target.item_code, source_parent.company)
		item_group = get_item_group_defaults(target.item_code, source_parent.company)
		target.cost_center = frappe.db.get_value("Project", obj.project, "cost_center") \
			or item.get("buying_cost_center") \
			or item_group.get("buying_cost_center")
Esempio n. 7
0
	def update_item(obj, target, source_parent):
		target.amount = flt(obj.amount) - flt(obj.billed_amt)
		target.base_amount = target.amount * flt(source_parent.conversion_rate)
		target.qty = target.amount / flt(obj.rate) if (flt(obj.rate) and flt(obj.billed_amt)) else flt(obj.qty)

		item = get_item_defaults(target.item_code, source_parent.company)
		item_group = get_item_group_defaults(target.item_code, source_parent.company)
		target.cost_center = frappe.db.get_value("Project", obj.project, "cost_center") \
			or item.get("buying_cost_center") \
			or item_group.get("buying_cost_center")
Esempio n. 8
0
	def update_item(source, target, source_parent):
		target.base_amount = (flt(source.qty) - flt(source.delivered_qty)) * flt(source.base_rate)
		target.amount = (flt(source.qty) - flt(source.delivered_qty)) * flt(source.rate)
		target.qty = flt(source.qty) - flt(source.delivered_qty)

		item = get_item_defaults(target.item_code, source_parent.company)
		item_group = get_item_group_defaults(target.item_code, source_parent.company)

		if item:
			target.cost_center = frappe.db.get_value("Project", source_parent.project, "cost_center") \
				or item.get("selling_cost_center") \
				or item_group.get("selling_cost_center")
Esempio n. 9
0
def get_item_cost_center(item_code=None, company=None, project=None, customer=None):
    cost_center = frappe.get_cached_value("Company", company, "cost_center")
    if not item_code:
        return cost_center
    item_defaults = get_item_defaults(item_code, company)
    item_group_defaults = get_item_group_defaults(item_code, company)
    args = {
        "project": project,
        "customer": customer,
        "cost_center": cost_center,
    }
    return get_default_cost_center(args, item_defaults, item_group_defaults, company)
Esempio n. 10
0
	def update_item(source, target, source_parent):
		target.amount = flt(source.amount) - flt(source.billed_amt)
		target.base_amount = target.amount * flt(source_parent.conversion_rate)
		target.qty = target.amount / flt(source.rate) if (source.rate and source.billed_amt) else source.qty - source.returned_qty

		if source_parent.project:
			target.cost_center = frappe.db.get_value("Project", source_parent.project, "cost_center")
		if not target.cost_center and target.item_code:
			item = get_item_defaults(target.item_code, source_parent.company)
			item_group = get_item_group_defaults(target.item_code, source_parent.company)
			target.cost_center = item.get("selling_cost_center") \
				or item_group.get("selling_cost_center")
Esempio n. 11
0
	def update_item(source, target, source_parent):
		target.base_amount = (flt(source.qty) - flt(source.delivered_qty)) * flt(source.base_rate)
		target.amount = (flt(source.qty) - flt(source.delivered_qty)) * flt(source.rate)
		target.qty = flt(source.qty) - flt(source.delivered_qty)

		item = get_item_defaults(target.item_code, source_parent.company)
		item_group = get_item_group_defaults(target.item_code, source_parent.company)

		if item:
			target.cost_center = frappe.db.get_value("Project", source_parent.project, "cost_center") \
				or item.get("buying_cost_center") \
				or item_group.get("buying_cost_center")
Esempio n. 12
0
	def update_item(source, target, source_parent):
		target.amount = flt(source.amount) - flt(source.billed_amt)
		target.base_amount = target.amount * flt(source_parent.conversion_rate)
		target.qty = target.amount / flt(source.rate) if (source.rate and source.billed_amt) else source.qty - source.returned_qty

		if source_parent.project:
			target.cost_center = frappe.db.get_value("Project", source_parent.project, "cost_center")
		if not target.cost_center and target.item_code:
			item = get_item_defaults(target.item_code, source_parent.company)
			item_group = get_item_group_defaults(target.item_code, source_parent.company)
			target.cost_center = item.get("selling_cost_center") \
				or item_group.get("selling_cost_center")
	def get_item_details(self, args=None, for_update=False):
		item = frappe.db.sql("""select i.name, i.stock_uom, i.description, i.image, i.item_name, i.item_group,
				i.has_batch_no, i.sample_quantity, i.has_serial_no,
				id.expense_account, id.buying_cost_center
			from `tabItem` i LEFT JOIN `tabItem Default` id ON i.name=id.parent and id.company=%s
			where i.name=%s
				and i.disabled=0
				and (i.end_of_life is null or i.end_of_life='0000-00-00' or i.end_of_life > %s)""",
			(self.company, args.get('item_code'), nowdate()), as_dict = 1)

		if not item:
			frappe.throw(_("Item {0} is not active or end of life has been reached").format(args.get("item_code")))

		item = item[0]
		item_group_defaults = get_item_group_defaults(item.name, self.company)

		ret = frappe._dict({
			'uom'			      	: item.stock_uom,
			'stock_uom'				: item.stock_uom,
			'description'		  	: item.description,
			'image'					: item.image,
			'item_name' 		  	: item.item_name,
			'cost_center'			: get_default_cost_center(args, item, item_group_defaults, self.company),
			'qty'					: args.get("qty"),
			'transfer_qty'			: args.get('qty'),
			'conversion_factor'		: 1,
			'batch_no'				: '',
			'actual_qty'			: 0,
			'basic_rate'			: 0,
			'serial_no'				: '',
			'has_serial_no'			: item.has_serial_no,
			'has_batch_no'			: item.has_batch_no,
			'sample_quantity'		: item.sample_quantity
		})

		# update uom
		if args.get("uom") and for_update:
			ret.update(get_uom_details(args.get('item_code'), args.get('uom'), args.get('qty')))

		args['posting_date'] = self.posting_date
		args['posting_time'] = self.posting_time

		stock_and_rate = get_warehouse_details(args) if args.get('warehouse') else {}
		ret.update(stock_and_rate)

		# automatically select batch for outgoing item
		if (args.get('s_warehouse', None) and args.get('qty') and
			ret.get('has_batch_no') and not args.get('batch_no')):
			args.batch_no = get_batch_no(args['item_code'], args['s_warehouse'], args['qty'])

		return ret
Esempio n. 14
0
def get_product_discount_rule(pricing_rule, item_details, args=None, doc=None):
    free_item = pricing_rule.free_item
    if pricing_rule.same_item and pricing_rule.get(
            "apply_on") != 'Transaction':
        free_item = item_details.item_code or args.item_code

    if not free_item:
        frappe.throw(
            _("Free item not set in the pricing rule {0}").format(
                get_link_to_form("Pricing Rule", pricing_rule.name)))

    item_details.free_item_data = {
        'item_code': free_item,
        'qty': pricing_rule.free_qty or 1,
        'rate': pricing_rule.free_item_rate or 0,
        'price_list_rate': pricing_rule.free_item_rate or 0,
        'is_free_item': 1
    }

    item_data = frappe.get_cached_value(
        'Item',
        free_item, ['item_name', 'description', 'stock_uom'],
        as_dict=1)

    item_details.free_item_data.update(item_data)
    item_details.free_item_data[
        'uom'] = pricing_rule.free_item_uom or item_data.stock_uom
    item_details.free_item_data['conversion_factor'] = get_conversion_factor(
        free_item,
        item_details.free_item_data['uom']).get("conversion_factor", 1)

    if item_details.get("parenttype") == 'Purchase Order':
        item_details.free_item_data[
            'schedule_date'] = doc.schedule_date if doc else today()

    if item_details.get("parenttype") == 'Sales Order':
        item_details.free_item_data[
            'delivery_date'] = doc.delivery_date if doc else today()

    company = doc.company
    if args and args.get("company"):
        company = args.get("company")

    if args:
        item_details.free_item_data[
            'income_account'] = get_default_income_account(
                args=args,
                item=get_item_defaults(free_item, company),
                item_group=get_item_group_defaults(free_item, company),
                brand=get_brand_defaults(free_item, company),
            )
Esempio n. 15
0
    def update_item(source, target, source_parent):
        target.base_amount = flt(source.base_rate)
        target.amount = flt(source.rate)
        target.is_maintenance_applicable_cf = source.is_maintenance_applicable_cf
        target.maintenance_for_years_cf = source.maintenance_for_years_cf
        target.qty = 1
        serial_no_warehouse = None
        if serial_no:
            target.serial_no = serial_no
            serial_no_warehouse = frappe.db.get_value('Serial No', serial_no,
                                                      'warehouse')
        target.warehouse = serial_no_warehouse or source.warehouse or None
        item = get_item_defaults(target.item_code, source_parent.company)
        item_group = get_item_group_defaults(target.item_code,
                                             source_parent.company)

        if item:
            target.cost_center = frappe.db.get_value("Project", source_parent.project, "cost_center") \
                or item.get("buying_cost_center") \
                or item_group.get("buying_cost_center")
Esempio n. 16
0
def get_valuation_rate(item_code, company, warehouse=None):
	item = get_item_defaults(item_code, company)
	item_group = get_item_group_defaults(item_code, company)
	# item = frappe.get_doc("Item", item_code)
	if item.get("is_stock_item"):
		if not warehouse:
			warehouse = item.get("default_warehouse") or item_group.get("default_warehouse")

		return frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse},
			["valuation_rate"], as_dict=True) or {"valuation_rate": 0}

	elif not item.get("is_stock_item"):
		valuation_rate =frappe.db.sql("""select sum(base_net_amount) / sum(qty*conversion_factor)
			from `tabPurchase Invoice Item`
			where item_code = %s and docstatus=1""", item_code)

		if valuation_rate:
			return {"valuation_rate": valuation_rate[0][0] or 0.0}
	else:
		return {"valuation_rate": 0.0}
Esempio n. 17
0
def get_material_request_items(row, sales_order, company, ignore_existing_ordered_qty, warehouse):
	total_qty = row['qty']
	projected_qty, actual_qty = get_bin_details(row)

	requested_qty = 0
	if ignore_existing_ordered_qty:
		requested_qty = total_qty
	elif total_qty > projected_qty:
		requested_qty = total_qty - projected_qty
	if requested_qty > 0 and requested_qty < row['min_order_qty']:
		requested_qty = row['min_order_qty']
	item_group_defaults = get_item_group_defaults(row.item_code, company)

	if not row['purchase_uom']:
		row['purchase_uom'] = row['stock_uom']

	if row['purchase_uom'] != row['stock_uom']:
		if not row['conversion_factor']:
			frappe.throw(_("UOM Conversion factor ({0} -> {1}) not found for item: {2}")
				.format(row['purchase_uom'], row['stock_uom'], row.item_code))
		requested_qty = requested_qty / row['conversion_factor']

	if frappe.db.get_value("UOM", row['purchase_uom'], "must_be_whole_number"):
		requested_qty = ceil(requested_qty)

	if requested_qty > 0:
		return {
			'item_code': row.item_code,
			'item_name': row.item_name,
			'quantity': requested_qty,
			'warehouse': warehouse or row.get('source_warehouse') \
				or row.get('default_warehouse') or item_group_defaults.get("default_warehouse"),
			'actual_qty': actual_qty,
			'min_order_qty': row['min_order_qty'],
			'sales_order': sales_order
		}
Esempio n. 18
0
def get_basic_details(args, item, overwrite_warehouse=True):
    """
	:param args: {
			"item_code": "",
			"warehouse": None,
			"customer": "",
			"conversion_rate": 1.0,
			"selling_price_list": None,
			"price_list_currency": None,
			"price_list_uom_dependant": None,
			"plc_conversion_rate": 1.0,
			"doctype": "",
			"name": "",
			"supplier": None,
			"transaction_date": None,
			"conversion_rate": 1.0,
			"buying_price_list": None,
			"is_subcontracted": "Yes" / "No",
			"ignore_pricing_rule": 0/1
			"project": "",
			barcode: "",
			serial_no: "",
			currency: "",
			update_stock: "",
			price_list: "",
			company: "",
			order_type: "",
			is_pos: "",
			project: "",
			qty: "",
			stock_qty: "",
			conversion_factor: "",
			against_blanket_order: 0/1
		}
	:param item: `item_code` of Item object
	:return: frappe._dict
	"""

    if not item:
        item = frappe.get_doc("Item", args.get("item_code"))

    if item.variant_of:
        item.update_template_tables()

    item_defaults = get_item_defaults(item.name, args.company)
    item_group_defaults = get_item_group_defaults(item.name, args.company)
    brand_defaults = get_brand_defaults(item.name, args.company)

    defaults = frappe._dict({
        'item_defaults': item_defaults,
        'item_group_defaults': item_group_defaults,
        'brand_defaults': brand_defaults
    })

    warehouse = get_item_warehouse(item, args, overwrite_warehouse, defaults)

    if args.get('doctype') == "Material Request" and not args.get(
            'material_request_type'):
        args['material_request_type'] = frappe.db.get_value(
            'Material Request',
            args.get('name'),
            'material_request_type',
            cache=True)

    expense_account = None

    if args.get('doctype') == 'Purchase Invoice' and item.is_fixed_asset:
        from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account
        expense_account = get_asset_category_account(
            fieldname="fixed_asset_account",
            item=args.item_code,
            company=args.company)

    #Set the UOM to the Default Sales UOM or Default Purchase UOM if configured in the Item Master
    if not args.get('uom'):
        if args.get('doctype') in sales_doctypes:
            args.uom = item.sales_uom if item.sales_uom else item.stock_uom
        elif (args.get('doctype') in ['Purchase Order', 'Purchase Receipt', 'Purchase Invoice']) or \
         (args.get('doctype') == 'Material Request' and args.get('material_request_type') == 'Purchase'):
            args.uom = item.purchase_uom if item.purchase_uom else item.stock_uom
        else:
            args.uom = item.stock_uom

    out = frappe._dict({
        "item_code":
        item.name,
        "item_name":
        item.item_name,
        "description":
        cstr(item.description).strip(),
        "image":
        cstr(item.image).strip(),
        "warehouse":
        warehouse,
        "income_account":
        get_default_income_account(args, item_defaults, item_group_defaults,
                                   brand_defaults),
        "expense_account":
        expense_account or get_default_expense_account(
            args, item_defaults, item_group_defaults, brand_defaults),
        "cost_center":
        get_default_cost_center(args, item_defaults, item_group_defaults,
                                brand_defaults),
        'has_serial_no':
        item.has_serial_no,
        'has_batch_no':
        item.has_batch_no,
        "batch_no":
        args.get("batch_no"),
        "uom":
        args.uom,
        "min_order_qty":
        flt(item.min_order_qty) if args.doctype == "Material Request" else "",
        "qty":
        flt(args.qty) or 1.0,
        "stock_qty":
        flt(args.qty) or 1.0,
        "price_list_rate":
        0.0,
        "base_price_list_rate":
        0.0,
        "rate":
        0.0,
        "base_rate":
        0.0,
        "amount":
        0.0,
        "base_amount":
        0.0,
        "net_rate":
        0.0,
        "net_amount":
        0.0,
        "discount_percentage":
        0.0,
        "supplier":
        get_default_supplier(args, item_defaults, item_group_defaults,
                             brand_defaults),
        "update_stock":
        args.get("update_stock")
        if args.get('doctype') in ['Sales Invoice', 'Purchase Invoice'] else 0,
        "delivered_by_supplier":
        item.delivered_by_supplier
        if args.get("doctype") in ["Sales Order", "Sales Invoice"] else 0,
        "is_fixed_asset":
        item.is_fixed_asset,
        "weight_per_unit":
        item.weight_per_unit,
        "weight_uom":
        item.weight_uom,
        "last_purchase_rate":
        item.last_purchase_rate
        if args.get("doctype") in ["Purchase Order"] else 0,
        "transaction_date":
        args.get("transaction_date"),
        "against_blanket_order":
        args.get("against_blanket_order"),
        "bom_no":
        item.get("default_bom")
    })

    if item.get("enable_deferred_revenue") or item.get(
            "enable_deferred_expense"):
        out.update(calculate_service_end_date(args, item))

    # calculate conversion factor
    if item.stock_uom == args.uom:
        out.conversion_factor = 1.0
    else:
        out.conversion_factor = args.conversion_factor or \
         get_conversion_factor(item.name, args.uom).get("conversion_factor")

    args.conversion_factor = out.conversion_factor
    out.stock_qty = out.qty * out.conversion_factor

    # calculate last purchase rate
    if args.get('doctype') in purchase_doctypes:
        from erpnext.buying.doctype.purchase_order.purchase_order import item_last_purchase_rate
        out.last_purchase_rate = item_last_purchase_rate(
            args.name, args.conversion_rate, item.name, out.conversion_factor)

    # if default specified in item is for another company, fetch from company
    for d in [["Account", "income_account", "default_income_account"],
              ["Account", "expense_account", "default_expense_account"],
              ["Cost Center", "cost_center", "cost_center"],
              ["Warehouse", "warehouse", ""]]:
        if not out[d[1]]:
            out[d[1]] = frappe.get_cached_value('Company', args.company,
                                                d[2]) if d[2] else None

    for fieldname in ("item_name", "item_group", "barcodes", "brand",
                      "stock_uom"):
        out[fieldname] = item.get(fieldname)

    if args.get("manufacturer"):
        part_no = get_item_manufacturer_part_no(args.get("item_code"),
                                                args.get("manufacturer"))
        if part_no:
            out["manufacturer_part_no"] = part_no
        else:
            out["manufacturer_part_no"] = None
            out["manufacturer"] = None
    else:
        data = frappe.get_value(
            "Item",
            item.name,
            ["default_item_manufacturer", "default_manufacturer_part_no"],
            as_dict=1)

        if data:
            out.update({
                "manufacturer":
                data.default_item_manufacturer,
                "manufacturer_part_no":
                data.default_manufacturer_part_no
            })

    child_doctype = args.doctype + ' Item'
    meta = frappe.get_meta(child_doctype)
    if meta.get_field("barcode"):
        update_barcode_value(out)

    return out
Esempio n. 19
0
def get_material_request_items(row, sales_order, company,
                               ignore_existing_ordered_qty,
                               include_safety_stock, warehouse, bin_dict):
    total_qty = row["qty"]

    required_qty = 0
    if ignore_existing_ordered_qty or bin_dict.get("projected_qty", 0) < 0:
        required_qty = total_qty
    elif total_qty > bin_dict.get("projected_qty", 0):
        required_qty = total_qty - bin_dict.get("projected_qty", 0)
    if required_qty > 0 and required_qty < row["min_order_qty"]:
        required_qty = row["min_order_qty"]
    item_group_defaults = get_item_group_defaults(row.item_code, company)

    if not row["purchase_uom"]:
        row["purchase_uom"] = row["stock_uom"]

    if row["purchase_uom"] != row["stock_uom"]:
        if not (row["conversion_factor"]
                or frappe.flags.show_qty_in_stock_uom):
            frappe.throw(
                _("UOM Conversion factor ({0} -> {1}) not found for item: {2}"
                  ).format(row["purchase_uom"], row["stock_uom"],
                           row.item_code))

            required_qty = required_qty / row["conversion_factor"]

    if frappe.db.get_value("UOM", row["purchase_uom"], "must_be_whole_number"):
        required_qty = ceil(required_qty)

    if include_safety_stock:
        required_qty += flt(row["safety_stock"])

    if required_qty > 0:
        return {
            "item_code":
            row.item_code,
            "item_name":
            row.item_name,
            "quantity":
            required_qty,
            "required_bom_qty":
            total_qty,
            "stock_uom":
            row.get("stock_uom"),
            "warehouse":
            warehouse or row.get("source_warehouse")
            or row.get("default_warehouse")
            or item_group_defaults.get("default_warehouse"),
            "safety_stock":
            row.safety_stock,
            "actual_qty":
            bin_dict.get("actual_qty", 0),
            "projected_qty":
            bin_dict.get("projected_qty", 0),
            "ordered_qty":
            bin_dict.get("ordered_qty", 0),
            "reserved_qty_for_production":
            bin_dict.get("reserved_qty_for_production", 0),
            "min_order_qty":
            row["min_order_qty"],
            "material_request_type":
            row.get("default_material_request_type"),
            "sales_order":
            sales_order,
            "description":
            row.get("description"),
            "uom":
            row.get("purchase_uom") or row.get("stock_uom"),
        }
def get_basic_details(args, item):
	"""
	:param args: {
			"item_code": "",
			"warehouse": None,
			"customer": "",
			"conversion_rate": 1.0,
			"selling_price_list": None,
			"price_list_currency": None,
			"price_list_uom_dependant": None,
			"plc_conversion_rate": 1.0,
			"doctype": "",
			"name": "",
			"supplier": None,
			"transaction_date": None,
			"conversion_rate": 1.0,
			"buying_price_list": None,
			"is_subcontracted": "Yes" / "No",
			"ignore_pricing_rule": 0/1
			"project": "",
			barcode: "",
			serial_no: "",
			currency: "",
			update_stock: "",
			price_list: "",
			company: "",
			order_type: "",
			is_pos: "",
			project: "",
			qty: "",
			stock_qty: "",
			conversion_factor: ""
		}
	:param item: `item_code` of Item object
	:return: frappe._dict
	"""

	if not item:
		item = frappe.get_doc("Item", args.get("item_code"))

	if item.variant_of:
		item.update_template_tables()

	from frappe.defaults import get_user_default_as_list
	user_default_warehouse_list = get_user_default_as_list('Warehouse')
	user_default_warehouse = user_default_warehouse_list[0] \
		if len(user_default_warehouse_list) == 1 else ""

	item_defaults = get_item_defaults(item.name, args.company)
	item_group_defaults = get_item_group_defaults(item.name, args.company)

	warehouse = args.get("set_warehouse") or user_default_warehouse or item_defaults.get("default_warehouse") or\
		item_group_defaults.get("default_warehouse") or args.warehouse

	if args.get('doctype') == "Material Request" and not args.get('material_request_type'):
		args['material_request_type'] = frappe.db.get_value('Material Request',
			args.get('name'), 'material_request_type', cache=True)

	#Set the UOM to the Default Sales UOM or Default Purchase UOM if configured in the Item Master
	if not args.uom:
		if args.get('doctype') in sales_doctypes:
			args.uom = item.sales_uom if item.sales_uom else item.stock_uom
		elif (args.get('doctype') in ['Purchase Order', 'Purchase Receipt', 'Purchase Invoice']) or \
			(args.get('doctype') == 'Material Request' and args.get('material_request_type') == 'Purchase'):
			args.uom = item.purchase_uom if item.purchase_uom else item.stock_uom
		else:
			args.uom = item.stock_uom

	out = frappe._dict({
		"item_code": item.name,
		"item_name": item.item_name,
		"description": cstr(item.description).strip(),
		"image": cstr(item.image).strip(),
		"warehouse": warehouse,
		"income_account": get_default_income_account(args, item_defaults, item_group_defaults),
		"expense_account": get_default_expense_account(args, item_defaults, item_group_defaults),
		"cost_center": get_default_cost_center(args, item_defaults, item_group_defaults),
		'has_serial_no': item.has_serial_no,
		'has_batch_no': item.has_batch_no,
		"batch_no": None,
		"item_tax_rate": json.dumps(dict(([d.tax_type, d.tax_rate] for d in
			item.get("taxes")))),
		"uom": args.uom,
		"min_order_qty": flt(item.min_order_qty) if args.doctype == "Material Request" else "",
		"qty": args.qty or 1.0,
		"stock_qty": args.qty or 1.0,
		"price_list_rate": 0.0,
		"base_price_list_rate": 0.0,
		"rate": 0.0,
		"base_rate": 0.0,
		"amount": 0.0,
		"base_amount": 0.0,
		"net_rate": 0.0,
		"net_amount": 0.0,
		"discount_percentage": 0.0,
		"supplier": get_default_supplier(args, item_defaults, item_group_defaults),
		"update_stock": args.get("update_stock") if args.get('doctype') in ['Sales Invoice', 'Purchase Invoice'] else 0,
		"delivered_by_supplier": item.delivered_by_supplier if args.get("doctype") in ["Sales Order", "Sales Invoice"] else 0,
		"is_fixed_asset": item.is_fixed_asset,
		"weight_per_unit":item.weight_per_unit,
		"weight_uom":item.weight_uom,
		"last_purchase_rate": item.last_purchase_rate if args.get("doctype") in ["Purchase Order"] else 0,
		"transaction_date": args.get("transaction_date")
	})

	if item.get("enable_deferred_revenue") or item.get("enable_deferred_expense"):
		out.update(calculate_service_end_date(args, item))

	# calculate conversion factor
	if item.stock_uom == args.uom:
		out.conversion_factor = 1.0
	else:
		out.conversion_factor = args.conversion_factor or \
			get_conversion_factor(item.name, args.uom).get("conversion_factor")

	args.conversion_factor = out.conversion_factor
	out.stock_qty = out.qty * out.conversion_factor

	# calculate last purchase rate
	if args.get('doctype') in purchase_doctypes:
		from erpnext.buying.doctype.purchase_order.purchase_order import item_last_purchase_rate
		out.last_purchase_rate = item_last_purchase_rate(args.name, args.conversion_rate, item.name, out.conversion_factor)

	# if default specified in item is for another company, fetch from company
	for d in [
		["Account", "income_account", "default_income_account"],
		["Account", "expense_account", "default_expense_account"],
		["Cost Center", "cost_center", "cost_center"],
		["Warehouse", "warehouse", ""]]:
			if not out[d[1]]:
				out[d[1]] = frappe.get_cached_value('Company',  args.company,  d[2]) if d[2] else None

	for fieldname in ("item_name", "item_group", "barcodes", "brand", "stock_uom"):
		out[fieldname] = item.get(fieldname)

	return out