def execute(filters=None): is_reposting_item_valuation_in_progress() filters = frappe._dict(filters or {}) include_uom = filters.get("include_uom") columns = get_columns() bin_list = get_bin_list(filters) item_map = get_item_map(filters.get("item_code"), include_uom) warehouse_company = {} data = [] conversion_factors = [] for bin in bin_list: item = item_map.get(bin.item_code) if not item: # likely an item that has reached its end of life continue # item = item_map.setdefault(bin.item_code, get_item(bin.item_code)) company = warehouse_company.setdefault( bin.warehouse, frappe.db.get_value("Warehouse", bin.warehouse, "company")) if filters.brand and filters.brand != item.brand: continue elif filters.item_group and filters.item_group != item.item_group: continue elif filters.company and filters.company != company: continue re_order_level = re_order_qty = 0 for d in item.get("reorder_levels"): if d.warehouse == bin.warehouse: re_order_level = d.warehouse_reorder_level re_order_qty = d.warehouse_reorder_qty shortage_qty = 0 if (re_order_level or re_order_qty) and re_order_level > bin.projected_qty: shortage_qty = re_order_level - flt(bin.projected_qty) data.append([ item.name, item.item_name, item.description, item.item_group, item.brand, bin.warehouse, item.stock_uom, bin.actual_qty, bin.planned_qty, bin.indented_qty, bin.ordered_qty, bin.reserved_qty, bin.reserved_qty_for_production, bin.reserved_qty_for_sub_contract, bin.projected_qty, re_order_level, re_order_qty, shortage_qty ]) if include_uom: conversion_factors.append(item.conversion_factor) update_included_uom_in_report(columns, data, include_uom, conversion_factors) return columns, data
def execute(filters=None): is_reposting_item_valuation_in_progress() filters = frappe._dict(filters or {}) columns = get_columns(filters) data = get_data(filters) chart = get_chart_data(columns) return columns, data, None, chart
def execute(filters=None): is_reposting_item_valuation_in_progress() include_uom = filters.get("include_uom") columns = get_columns() items = get_items(filters) sl_entries = get_stock_ledger_entries(filters, items) item_details = get_item_details(items, sl_entries, include_uom) opening_row = get_opening_balance(filters, columns, sl_entries) precision = cint( frappe.db.get_single_value("System Settings", "float_precision")) data = [] conversion_factors = [] if opening_row: data.append(opening_row) conversion_factors.append(0) actual_qty = stock_value = 0 available_serial_nos = {} for sle in sl_entries: item_detail = item_details[sle.item_code] sle.update(item_detail) if filters.get("batch_no"): actual_qty += flt(sle.actual_qty, precision) stock_value += sle.stock_value_difference if sle.voucher_type == 'Stock Reconciliation' and not sle.actual_qty: actual_qty = sle.qty_after_transaction stock_value = sle.stock_value sle.update({ "qty_after_transaction": actual_qty, "stock_value": stock_value }) sle.update({ "in_qty": max(sle.actual_qty, 0), "out_qty": min(sle.actual_qty, 0) }) if sle.serial_no: update_available_serial_nos(available_serial_nos, sle) data.append(sle) if include_uom: conversion_factors.append(item_detail.conversion_factor) update_included_uom_in_report(columns, data, include_uom, conversion_factors) return columns, data
def execute(filters=None): is_reposting_item_valuation_in_progress() if not filters: filters = {} validate_filters(filters) from_date = filters.get('from_date') to_date = filters.get('to_date') if filters.get("company"): company_currency = erpnext.get_company_currency(filters.get("company")) else: company_currency = frappe.db.get_single_value( "Global Defaults", "default_currency") include_uom = filters.get("include_uom") columns = get_columns(filters) items = get_items(filters) sle = get_stock_ledger_entries(filters, items) if filters.get('show_stock_ageing_data'): filters['show_warehouse_wise_stock'] = True item_wise_fifo_queue = get_fifo_queue(filters, sle) # if no stock ledger entry found return if not sle: return columns, [] iwb_map = get_item_warehouse_map(filters, sle) item_map = get_item_details(items, sle, filters) item_reorder_detail_map = get_item_reorder_details(item_map.keys()) data = [] conversion_factors = {} def _func(x): return x[1] for (company, item, warehouse) in sorted(iwb_map): if item_map.get(item): qty_dict = iwb_map[(company, item, warehouse)] item_reorder_level = 0 item_reorder_qty = 0 if item + warehouse in item_reorder_detail_map: item_reorder_level = item_reorder_detail_map[item + warehouse]["warehouse_reorder_level"] item_reorder_qty = item_reorder_detail_map[item + warehouse]["warehouse_reorder_qty"] report_data = { 'currency': company_currency, 'item_code': item, 'warehouse': warehouse, 'company': company, 'reorder_level': item_reorder_level, 'reorder_qty': item_reorder_qty, } report_data.update(item_map[item]) report_data.update(qty_dict) if include_uom: conversion_factors.setdefault( item, item_map[item].conversion_factor) if filters.get('show_stock_ageing_data'): fifo_queue = item_wise_fifo_queue[( item, warehouse)].get('fifo_queue') stock_ageing_data = { 'average_age': 0, 'earliest_age': 0, 'latest_age': 0 } if fifo_queue: fifo_queue = sorted(filter(_func, fifo_queue), key=_func) if not fifo_queue: continue stock_ageing_data['average_age'] = get_average_age( fifo_queue, to_date) stock_ageing_data['earliest_age'] = date_diff( to_date, fifo_queue[0][1]) stock_ageing_data['latest_age'] = date_diff( to_date, fifo_queue[-1][1]) report_data.update(stock_ageing_data) data.append(report_data) add_additional_uom_columns(columns, data, include_uom, conversion_factors) return columns, data
def execute(filters=None): is_reposting_item_valuation_in_progress() if not filters: filters = {} validate_filters(filters) columns = get_columns(filters) items = get_items(filters) sle = get_stock_ledger_entries(filters, items) item_map = get_item_details(items, sle, filters) iwb_map = get_item_warehouse_map(filters, sle) warehouse_list = get_warehouse_list(filters) item_ageing = get_fifo_queue(filters) data = [] item_balance = {} item_value = {} for (company, item, warehouse) in sorted(iwb_map): if not item_map.get(item): continue row = [] qty_dict = iwb_map[(company, item, warehouse)] item_balance.setdefault((item, item_map[item]["item_group"]), []) total_stock_value = 0.00 for wh in warehouse_list: row += [qty_dict.bal_qty] if wh.name in warehouse else [0.00] total_stock_value += qty_dict.bal_val if wh.name in warehouse else 0.00 item_balance[(item, item_map[item]["item_group"])].append(row) item_value.setdefault((item, item_map[item]["item_group"]), []) item_value[(item, item_map[item]["item_group"])].append(total_stock_value) # sum bal_qty by item for (item, item_group), wh_balance in iteritems(item_balance): if not item_ageing.get(item): continue total_stock_value = sum(item_value[(item, item_group)]) row = [item, item_group, total_stock_value] fifo_queue = item_ageing[item]["fifo_queue"] average_age = 0.00 if fifo_queue: average_age = get_average_age(fifo_queue, filters["to_date"]) row += [average_age] bal_qty = [sum(bal_qty) for bal_qty in zip(*wh_balance)] total_qty = sum(bal_qty) if len(warehouse_list) > 1: row += [total_qty] row += bal_qty if total_qty > 0: data.append(row) elif not filters.get("filter_total_zero_qty"): data.append(row) add_warehouse_column(columns, warehouse_list) return columns, data
def execute(filters: Optional[StockBalanceFilter] = None): is_reposting_item_valuation_in_progress() if not filters: filters = {} if filters.get("company"): company_currency = erpnext.get_company_currency(filters.get("company")) else: company_currency = frappe.db.get_single_value("Global Defaults", "default_currency") include_uom = filters.get("include_uom") columns = get_columns(filters) items = get_items(filters) sle = get_stock_ledger_entries(filters, items) if filters.get("show_stock_ageing_data"): filters["show_warehouse_wise_stock"] = True item_wise_fifo_queue = FIFOSlots(filters, sle).generate() # if no stock ledger entry found return if not sle: return columns, [] iwb_map = get_item_warehouse_map(filters, sle) item_map = get_item_details(items, sle, filters) item_reorder_detail_map = get_item_reorder_details(item_map.keys()) data = [] conversion_factors = {} _func = itemgetter(1) to_date = filters.get("to_date") for (company, item, warehouse) in sorted(iwb_map): if item_map.get(item): qty_dict = iwb_map[(company, item, warehouse)] item_reorder_level = 0 item_reorder_qty = 0 if item + warehouse in item_reorder_detail_map: item_reorder_level = item_reorder_detail_map[ item + warehouse]["warehouse_reorder_level"] item_reorder_qty = item_reorder_detail_map[ item + warehouse]["warehouse_reorder_qty"] report_data = { "currency": company_currency, "item_code": item, "warehouse": warehouse, "company": company, "reorder_level": item_reorder_level, "reorder_qty": item_reorder_qty, } report_data.update(item_map[item]) report_data.update(qty_dict) if include_uom: conversion_factors.setdefault(item, item_map[item].conversion_factor) if filters.get("show_stock_ageing_data"): fifo_queue = item_wise_fifo_queue[( item, warehouse)].get("fifo_queue") stock_ageing_data = { "average_age": 0, "earliest_age": 0, "latest_age": 0 } if fifo_queue: fifo_queue = sorted(filter(_func, fifo_queue), key=_func) if not fifo_queue: continue stock_ageing_data["average_age"] = get_average_age( fifo_queue, to_date) stock_ageing_data["earliest_age"] = date_diff( to_date, fifo_queue[0][1]) stock_ageing_data["latest_age"] = date_diff( to_date, fifo_queue[-1][1]) report_data.update(stock_ageing_data) data.append(report_data) add_additional_uom_columns(columns, data, include_uom, conversion_factors) return columns, data