def update_raw_materials_supplied(self, item, raw_material_table, rm_supplied_idx): bom_items = self.get_items_from_default_bom(item.item_code) raw_materials_cost = 0 for bom_item in bom_items: # check if exists exists = 0 for d in self.get(raw_material_table): if d.main_item_code == item.item_code and d.rm_item_code == bom_item.item_code \ and d.reference_name == item.name: rm, exists = d, 1 break if not exists: rm = self.append(raw_material_table, {}) required_qty = flt(bom_item.qty_consumed_per_unit) * flt( item.qty) * flt(item.conversion_factor) rm.reference_name = item.name rm.bom_detail_no = bom_item.name rm.main_item_code = item.item_code rm.rm_item_code = bom_item.item_code rm.stock_uom = bom_item.stock_uom rm.required_qty = required_qty rm.conversion_factor = item.conversion_factor rm.idx = rm_supplied_idx if self.doctype == "Purchase Receipt": rm.consumed_qty = required_qty rm.description = bom_item.description if item.batch_no and not rm.batch_no: rm.batch_no = item.batch_no rm_supplied_idx += 1 # get raw materials rate if self.doctype == "Purchase Receipt": from erpnext.stock.utils import get_incoming_rate rm.rate = get_incoming_rate({ "item_code": bom_item.item_code, "warehouse": self.supplier_warehouse, "posting_date": self.posting_date, "posting_time": self.posting_time, "qty": -1 * required_qty, "serial_no": rm.serial_no }) if not rm.rate: from erpnext.stock.stock_ledger import get_valuation_rate rm.rate = get_valuation_rate(bom_item.item_code, self.supplier_warehouse) else: rm.rate = bom_item.rate rm.amount = required_qty * flt(rm.rate) raw_materials_cost += flt(rm.amount) if self.doctype == "Purchase Receipt": item.rm_supp_cost = raw_materials_cost
def update_raw_materials_supplied_based_on_stock_entries(self, raw_material_table): self.set(raw_material_table, []) purchase_orders = [d.purchase_order for d in self.items] if purchase_orders: items = get_subcontracted_raw_materials_from_se(purchase_orders) backflushed_raw_materials = get_backflushed_subcontracted_raw_materials_from_se(purchase_orders, self.name) for d in items: qty = d.qty - backflushed_raw_materials.get(d.item_code, 0) rm = self.append(raw_material_table, {}) rm.rm_item_code = d.item_code rm.item_name = d.item_name rm.main_item_code = d.main_item_code rm.description = d.description rm.stock_uom = d.stock_uom rm.required_qty = qty rm.consumed_qty = qty rm.serial_no = d.serial_no rm.batch_no = d.batch_no # get raw materials rate from erpnext.stock.utils import get_incoming_rate rm.rate = get_incoming_rate({ "item_code": d.item_code, "warehouse": self.supplier_warehouse, "posting_date": self.posting_date, "posting_time": self.posting_time, "qty": -1 * qty, "serial_no": rm.serial_no }) if not rm.rate: rm.rate = get_valuation_rate(d.item_code, self.supplier_warehouse, self.doctype, self.name, currency=self.company_currency, company = self.company) rm.amount = qty * flt(rm.rate)
def get_incoming_rate(args): """Get Incoming Rate based on valuation method""" from erpnext.stock.stock_ledger import get_previous_sle, get_valuation_rate if isinstance(args, basestring): args = json.loads(args) in_rate = 0 if (args.get("serial_no") or "").strip(): in_rate = get_avg_purchase_rate(args.get("serial_no")) else: valuation_method = get_valuation_method(args.get("item_code")) previous_sle = get_previous_sle(args) if valuation_method == 'FIFO': if previous_sle: previous_stock_queue = json.loads(previous_sle.get('stock_queue', '[]') or '[]') in_rate = get_fifo_rate(previous_stock_queue, args.get("qty") or 0) if previous_stock_queue else 0 elif valuation_method == 'Moving Average': in_rate = previous_sle.get('valuation_rate') or 0 if not in_rate: voucher_no = args.get('voucher_no') or args.get('name') in_rate = get_valuation_rate(args.get('item_code'), args.get('warehouse'), args.get('voucher_type'), voucher_no, args.get('allow_zero_valuation'), currency=erpnext.get_company_currency(args.get('company')), company=args.get('company')) return in_rate
def update_stock_ledger_entries(self, sle): sle.valuation_rate = get_valuation_rate(sle.item_code, sle.warehouse, sle.voucher_type, sle.voucher_no) sle.stock_value = flt(sle.qty_after_transaction) * flt(sle.valuation_rate) sle.stock_value_difference = sle.stock_value sle.doctype="Stock Ledger Entry" frappe.get_doc(sle).db_update()
def get_average_buying_rate(self, row, item_code): if not item_code in self.average_buying_rate: if item_code in self.non_stock_items: self.average_buying_rate[item_code] = flt( 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)[0][0]) else: row.voucher_type = row.parenttype row.voucher_no = row.parent average_buying_rate = get_incoming_rate(row) if not average_buying_rate: average_buying_rate = get_valuation_rate( item_code, row.warehouse, row.parenttype, row.parent, allow_zero_rate=row.allow_zero_valuation, currency=self.filters.currency, company=self.filters.company) self.average_buying_rate[item_code] = flt(average_buying_rate) return self.average_buying_rate[item_code]
def get_incoming_rate(args, raise_error_if_no_rate=True): """Get Incoming Rate based on valuation method""" from erpnext.stock.stock_ledger import get_previous_sle, get_valuation_rate if isinstance(args, string_types): args = json.loads(args) in_rate = 0 if (args.get("serial_no") or "").strip(): in_rate = get_avg_purchase_rate(args.get("serial_no")) else: valuation_method = get_valuation_method(args.get("item_code")) previous_sle = get_previous_sle(args) if valuation_method == 'FIFO': if previous_sle: previous_stock_queue = json.loads( previous_sle.get('stock_queue', '[]') or '[]') in_rate = get_fifo_rate(previous_stock_queue, args.get("qty") or 0) if previous_stock_queue else 0 elif valuation_method == 'Moving Average': in_rate = previous_sle.get('valuation_rate') or 0 if not in_rate: voucher_no = args.get('voucher_no') or args.get('name') in_rate = get_valuation_rate(args.get('item_code'), args.get('warehouse'), args.get('voucher_type'), voucher_no, args.get('allow_zero_valuation'), currency=erpnext.get_company_currency( args.get('company')), company=args.get('company'), raise_error_if_no_rate=True) return in_rate
def update_stock_ledger_entries(self, sle): sle.valuation_rate = get_valuation_rate(sle.item_code, sle.warehouse, self.doctype, self.name, currency=self.company_currency, company=self.company) sle.stock_value = flt(sle.qty_after_transaction) * flt( sle.valuation_rate) sle.stock_value_difference = flt(sle.actual_qty) * flt( sle.valuation_rate) incoming_rate_field = "" if flt(sle.actual_qty) > 0: sle.incoming_rate = sle.valuation_rate incoming_rate_field = ", incoming_rate = %(incoming_rate)s" if sle.name: frappe.db.sql(""" update `tabStock Ledger Entry` set stock_value = %(stock_value)s, valuation_rate = %(valuation_rate)s, stock_value_difference = %(stock_value_difference)s {0} where name = %(name)s """.format(incoming_rate_field), sle) # nosec return sle
def append_raw_material_to_be_backflushed(self, fg_item_doc, raw_material_data, qty): rm = self.append('supplied_items', {}) rm.update(raw_material_data) if not rm.main_item_code: rm.main_item_code = fg_item_doc.item_code rm.reference_name = fg_item_doc.name rm.required_qty = qty rm.consumed_qty = qty if not raw_material_data.get('non_stock_item'): from erpnext.stock.utils import get_incoming_rate rm.rate = get_incoming_rate({ "item_code": raw_material_data.rm_item_code, "warehouse": self.supplier_warehouse, "posting_date": self.posting_date, "posting_time": self.posting_time, "qty": -1 * qty, "serial_no": rm.serial_no }) if not rm.rate: rm.rate = get_valuation_rate(raw_material_data.rm_item_code, self.supplier_warehouse, self.doctype, self.name, currency=self.company_currency, company=self.company) rm.amount = qty * flt(rm.rate) fg_item_doc.rm_supp_cost += rm.amount
def update_stock_ledger_entries(self, sle): sle.valuation_rate = get_valuation_rate(sle.item_code, sle.warehouse, self.doctype, self.name, currency=self.company_currency, company=self.company) sle.stock_value = flt(sle.qty_after_transaction) * flt( sle.valuation_rate) sle.stock_value_difference = flt(sle.actual_qty) * flt( sle.valuation_rate) if sle.name: frappe.db.sql( """ update `tabStock Ledger Entry` set stock_value = %(stock_value)s, valuation_rate = %(valuation_rate)s, stock_value_difference = %(stock_value_difference)s where name = %(name)s""", (sle)) return sle
def get_batch_values(self, sle): incoming_rate = flt(sle.incoming_rate) actual_qty = flt(sle.actual_qty) batch_no = cstr(sle.batch_no) item_code = cstr(sle.item_code) conditions = "and item_code = '{item_code}' and batch_no = '{batch_no}' ".format( item_code=item_code, batch_no=batch_no) if sle.get("warehouse"): warehouse = sle.get("warehouse") conditions += " and warehouse = '{warehouse}' ".format( warehouse=warehouse) if sle.get("company"): company = sle.get("company") conditions += " and company = '{company}' ".format(company=company) if incoming_rate < 0: # wrong incoming rate incoming_rate = self.wh_data.valuation_rate stock_value_change = 0 if incoming_rate: stock_value_change = actual_qty * incoming_rate elif actual_qty < 0: # In case of delivery/stock issue, get average purchase rate # of serial nos of current entry if not sle.is_cancelled: stock_value_change = actual_qty * flt( frappe.db.sql( """SELECT incoming_rate FROM `tabStock Ledger Entry` WHERE actual_qty > 0 and docstatus = 1 and is_cancelled = 0 {conditions} order by posting_date desc, posting_time desc, creation desc""" .format(conditions=conditions))[0][0]) else: stock_value_change = actual_qty * sle.outgoing_rate new_stock_qty = self.wh_data.qty_after_transaction + actual_qty if new_stock_qty > 0: new_stock_value = (self.wh_data.qty_after_transaction * self.wh_data.valuation_rate) + stock_value_change if new_stock_value >= 0: # calculate new valuation rate only if stock value is positive # else it remains the same as that of previous entry self.wh_data.valuation_rate = new_stock_value / new_stock_qty if not self.wh_data.valuation_rate and sle.voucher_detail_no: allow_zero_rate = self.check_if_allow_zero_valuation_rate( sle.voucher_type, sle.voucher_detail_no) if not allow_zero_rate: self.wh_data.valuation_rate = get_valuation_rate( sle.item_code, sle.warehouse, sle.voucher_type, sle.voucher_no, self.allow_zero_rate, currency=erpnext.get_company_currency(sle.company))
def update_stock_ledger_entries(self, sle): sle.valuation_rate = get_valuation_rate(sle.item_code, sle.warehouse, sle.voucher_type, sle.voucher_no) sle.stock_value = flt(sle.qty_after_transaction) * flt(sle.valuation_rate) sle.stock_value_difference = sle.stock_value if sle.name: frappe.db.sql(""" update `tabStock Ledger Entry` set stock_value = %(stock_value)s, valuation_rate = %(valuation_rate)s, stock_value_difference = %(stock_value_difference)s where name = %(name)s""", (sle))
def update_raw_materials_supplied(self, item, raw_material_table, rm_supplied_idx): bom_items = self.get_items_from_default_bom(item.item_code) raw_materials_cost = 0 for bom_item in bom_items: # check if exists exists = 0 for d in self.get(raw_material_table): if d.main_item_code == item.item_code and d.rm_item_code == bom_item.item_code \ and d.reference_name == item.name: rm, exists = d, 1 break if not exists: rm = self.append(raw_material_table, {}) required_qty = flt(bom_item.qty_consumed_per_unit) * flt(item.qty) * flt(item.conversion_factor) rm.reference_name = item.name rm.bom_detail_no = bom_item.name rm.main_item_code = item.item_code rm.rm_item_code = bom_item.item_code rm.stock_uom = bom_item.stock_uom rm.required_qty = required_qty rm.conversion_factor = item.conversion_factor rm.idx = rm_supplied_idx if self.doctype == "Purchase Receipt": rm.consumed_qty = required_qty rm.description = bom_item.description if item.batch_no and not rm.batch_no: rm.batch_no = item.batch_no rm_supplied_idx += 1 # get raw materials rate if self.doctype == "Purchase Receipt": from erpnext.stock.utils import get_incoming_rate rm.rate = get_incoming_rate({ "item_code": bom_item.item_code, "warehouse": self.supplier_warehouse, "posting_date": self.posting_date, "posting_time": self.posting_time, "qty": -1 * required_qty, "serial_no": rm.serial_no }) if not rm.rate: from erpnext.stock.stock_ledger import get_valuation_rate rm.rate = get_valuation_rate(bom_item.item_code, self.supplier_warehouse) else: rm.rate = bom_item.rate rm.amount = required_qty * flt(rm.rate) raw_materials_cost += flt(rm.amount) if self.doctype == "Purchase Receipt": item.rm_supp_cost = raw_materials_cost
def set_incoming_rate(self): for d in self.items: if d.s_warehouse: args = self.get_args_for_incoming_rate(d) d.basic_rate = get_incoming_rate(args) elif d.allow_zero_valuation_rate and not d.s_warehouse: d.basic_rate = 0.0 elif d.t_warehouse and not d.basic_rate: d.basic_rate = get_valuation_rate(d.item_code, d.t_warehouse, self.doctype, d.name, d.allow_zero_valuation_rate, currency=erpnext.get_company_currency(self.company))
def get_incoming_rate(args, raise_error_if_no_rate=True): """Get Incoming Rate based on valuation method""" from erpnext.stock.stock_ledger import ( get_batch_incoming_rate, get_previous_sle, get_valuation_rate, ) if isinstance(args, str): args = json.loads(args) voucher_no = args.get("voucher_no") or args.get("name") in_rate = None if (args.get("serial_no") or "").strip(): in_rate = get_avg_purchase_rate(args.get("serial_no")) elif args.get("batch_no") and frappe.db.get_value( "Batch", args.get("batch_no"), "use_batchwise_valuation", cache=True): in_rate = get_batch_incoming_rate( item_code=args.get("item_code"), warehouse=args.get("warehouse"), batch_no=args.get("batch_no"), posting_date=args.get("posting_date"), posting_time=args.get("posting_time"), ) else: valuation_method = get_valuation_method(args.get("item_code")) previous_sle = get_previous_sle(args) if valuation_method in ("FIFO", "LIFO"): if previous_sle: previous_stock_queue = json.loads( previous_sle.get("stock_queue", "[]") or "[]") in_rate = (_get_fifo_lifo_rate(previous_stock_queue, args.get("qty") or 0, valuation_method) if previous_stock_queue else 0) elif valuation_method == "Moving Average": in_rate = previous_sle.get("valuation_rate") or 0 if in_rate is None: in_rate = get_valuation_rate( args.get("item_code"), args.get("warehouse"), args.get("voucher_type"), voucher_no, args.get("allow_zero_valuation"), currency=erpnext.get_company_currency(args.get("company")), company=args.get("company"), raise_error_if_no_rate=raise_error_if_no_rate, batch_no=args.get("batch_no"), ) return flt(in_rate)
def get_batch_values(self, sle): incoming_rate = flt(sle.incoming_rate) actual_qty = flt(sle.actual_qty) batch_no = cstr(sle.batch_no) item_code = cstr(sle.item_code) conditions = f"and item_code = '{item_code}' and batch_no = '{batch_no}' " if sle.get("warehouse"): warehouse = sle.get("warehouse") conditions += f" and warehouse = '{warehouse}' " if sle.get("company"): company = sle.get("company") conditions += f" and company = '{company}' " if incoming_rate < 0: # wrong incoming rate incoming_rate = self.valuation_rate stock_value_change = 0 if incoming_rate: stock_value_change = actual_qty * incoming_rate elif actual_qty < 0: # In case of delivery/stock issue, get average purchase rate # of serial nos of current entry stock_value_change = actual_qty * flt( frappe.db.sql( f"""SELECT incoming_rate FROM `tabStock Ledger Entry` WHERE actual_qty > 0 and docstatus = 1 {conditions}""")[0][0]) new_stock_qty = self.qty_after_transaction + actual_qty if new_stock_qty > 0: new_stock_value = (self.qty_after_transaction * self.valuation_rate) + stock_value_change if new_stock_value >= 0: # calculate new valuation rate only if stock value is positive # else it remains the same as that of previous entry self.valuation_rate = new_stock_value / new_stock_qty if not self.valuation_rate and sle.voucher_detail_no: allow_zero_rate = update_entries_after.check_if_allow_zero_valuation_rate( sle.voucher_type, sle.voucher_detail_no) if not allow_zero_rate: self.valuation_rate = get_valuation_rate( sle.item_code, sle.warehouse, sle.voucher_type, sle.voucher_no, self.allow_zero_rate, currency=erpnext.get_company_currency(sle.company))
def update_stock_ledger_entries(self, sle): sle.valuation_rate = get_valuation_rate(sle.item_code, sle.warehouse, sle.voucher_type, sle.voucher_no) sle.stock_value = flt(sle.qty_after_transaction) * flt( sle.valuation_rate) sle.stock_value_difference = sle.stock_value if sle.name: frappe.db.sql( """ update `tabStock Ledger Entry` set stock_value = %(stock_value)s, valuation_rate = %(valuation_rate)s, stock_value_difference = %(stock_value_difference)s where name = %(name)s""", (sle))
def get_incoming_rate(args, raise_error_if_no_rate=True): """Get Incoming Rate based on valuation method""" from erpnext.stock.stock_ledger import get_previous_sle, get_valuation_rate from erpnext.stock.utils import get_fifo_rate, get_avg_purchase_rate, get_valuation_method from erpnext.stock.stock_ledger import get_previous_sle from six import string_types if isinstance(args, string_types): args = json.loads(args) in_rate = 0 #finbyz changes batch_wise_cost = cint( frappe.db.get_single_value( "Stock Settings", 'exact_cost_valuation_for_batch_wise_items')) # finbyz changes #finbyz changes if args.get("batch_no") and batch_wise_cost: in_rate = get_batch_rate(args) #frappe.msgprint(f"inside:{in_rate}") elif (args.get("serial_no") or "").strip(): in_rate = get_avg_purchase_rate(args.get("serial_no")) else: valuation_method = get_valuation_method(args.get("item_code")) previous_sle = get_previous_sle(args) if valuation_method == 'FIFO': if previous_sle: previous_stock_queue = json.loads( previous_sle.get('stock_queue', '[]') or '[]') in_rate = get_fifo_rate(previous_stock_queue, args.get("qty") or 0) if previous_stock_queue else 0 elif valuation_method == 'Moving Average': in_rate = previous_sle.get('valuation_rate') or 0 if not in_rate: voucher_no = args.get('voucher_no') or args.get('name') in_rate = get_valuation_rate( args.get('item_code'), args.get('warehouse'), args.get('voucher_type'), voucher_no, args.get('allow_zero_valuation'), currency=erpnext.get_company_currency(args.get('company')), company=args.get('company'), raise_error_if_no_rate=raise_error_if_no_rate) #frappe.msgprint(str(in_rate)) return in_rate
def get_average_buying_rate(self, row, item_code): if not item_code in self.average_buying_rate: if item_code in self.non_stock_items: self.average_buying_rate[item_code] = flt(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)[0][0]) else: average_buying_rate = get_incoming_rate(row) if not average_buying_rate: average_buying_rate = get_valuation_rate(item_code, row.warehouse, allow_zero_rate=True) self.average_buying_rate[item_code] = average_buying_rate return self.average_buying_rate[item_code]
def set_incoming_rate(self): precision = cint(frappe.db.get_default("float_precision")) for d in self.items: if d.source_warehouse: args = self.get_args_for_incoming_rate(d) d.basic_rate = flt(get_incoming_rate(args), precision) elif not d.source_warehouse: d.basic_rate = 0.0 elif self.warehouse and not d.basic_rate: d.basic_rate = flt(get_valuation_rate(d.item_code, self.warehouse, self.doctype, d.name, 1, currency=erpnext.get_company_currency(self.company)), precision) d.basic_amount = d.basic_rate * d.qty
def get_incoming_rate(args, raise_error_if_no_rate=True): """Get Incoming Rate based on valuation method""" from erpnext.stock.stock_ledger import get_previous_sle, get_valuation_rate if isinstance(args, string_types): args = json.loads(args) in_rate = 0 if (args.get("serial_no") or "").strip(): in_rate = get_avg_purchase_rate(args.get("serial_no")) else: valuation_method = get_valuation_method(args.get("item_code")) previous_sle = get_previous_sle(args) if valuation_method == 'FIFO': if previous_sle: previous_stock_queue = json.loads( previous_sle.get('stock_queue', '[]') or '[]') in_rate = get_fifo_rate(previous_stock_queue, args.get("qty") or 0) if previous_stock_queue else 0 elif valuation_method == 'Moving Average': in_rate = previous_sle.get('valuation_rate') or 0 in_uom = previous_sle.get('stock_uom') required_uom = args.get("uom") or args.get("stock_uom") # frappe.errprint(in_rate) # frappe.errprint(required_uom) # frappe.errprint(in_uom) # if required_uom: # if required_uom != in_uom: # from erpnext.stock.get_item_details import get_conversion_factor # item_code = args.get("item_code") # conversion_factor = flt(get_conversion_factor(item_code, required_uom)['conversion_factor']) # in_rate = flt(in_rate) * flt(conversion_factor) # frappe.errprint(conversion_factor) if not in_rate: voucher_no = args.get('voucher_no') or args.get('name') in_rate = get_valuation_rate(args.get('item_code'), args.get('warehouse'), args.get('voucher_type'), voucher_no, args.get('allow_zero_valuation'), currency=erpnext.get_company_currency( args.get('company')), company=args.get('company'), raise_error_if_no_rate=True) return in_rate
def get_average_buying_rate(self, row, item_code): if not item_code in self.average_buying_rate: if item_code in self.non_stock_items: self.average_buying_rate[item_code] = flt( 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)[0][0]) else: average_buying_rate = get_incoming_rate(row) if not average_buying_rate: average_buying_rate = get_valuation_rate( item_code, row.warehouse, allow_zero_rate=True) self.average_buying_rate[item_code] = average_buying_rate return self.average_buying_rate[item_code]
def set_incoming_rate(self): for d in self.items: if d.source_warehouse: args = self.get_args_for_incoming_rate(d) d.basic_rate = get_incoming_rate(args) elif not d.source_warehouse: d.basic_rate = 0.0 elif self.warehouse and not d.basic_rate: d.basic_rate = get_valuation_rate( d.item_code, self.warehouse, self.doctype, d.name, 1, currency=erpnext.get_company_currency(self.company)) d.basic_amount = d.basic_rate * d.quantity
def update_stock_ledger_entries(self, sle): sle.valuation_rate = get_valuation_rate(sle.item_code, sle.warehouse, self.doctype, self.name, currency=self.company_currency, company=self.company) sle.stock_value = flt(sle.qty_after_transaction) * flt(sle.valuation_rate) sle.stock_value_difference = flt(sle.actual_qty) * flt(sle.valuation_rate) if sle.name: frappe.db.sql(""" update `tabStock Ledger Entry` set stock_value = %(stock_value)s, valuation_rate = %(valuation_rate)s, stock_value_difference = %(stock_value_difference)s where name = %(name)s""", (sle)) return sle
def get_incoming_rate_for_sales_return(self, item_code, warehouse, against_document): incoming_rate = 0.0 if against_document and item_code: incoming_rate = frappe.db.sql( """select abs(stock_value_difference / actual_qty) from `tabStock Ledger Entry` where voucher_type = %s and voucher_no = %s and item_code = %s limit 1""", (self.doctype, against_document, item_code)) incoming_rate = incoming_rate[0][0] if incoming_rate else 0.0 else: incoming_rate = get_valuation_rate(item_code, warehouse, self.doctype, against_document, company=self.company, currency=self.currency) return incoming_rate
def get_batch_values(self, sle): incoming_rate = flt(sle.incoming_rate) actual_qty = flt(sle.actual_qty) batch_no = cstr(sle.batch_no) if incoming_rate < 0: # wrong incoming rate incoming_rate = self.valuation_rate stock_value_change = 0 if incoming_rate: stock_value_change = actual_qty * incoming_rate elif actual_qty < 0: # In case of delivery/stock issue, get average purchase rate # of serial nos of current entry stock_value_change = actual_qty * flt( frappe.db.sql( """select valuation_rate from `tabBatch` where name = %s """, batch_no)[0][0]) new_stock_qty = self.qty_after_transaction + actual_qty if new_stock_qty > 0: new_stock_value = (self.qty_after_transaction * self.valuation_rate) + stock_value_change if new_stock_value >= 0: # calculate new valuation rate only if stock value is positive # else it remains the same as that of previous entry self.valuation_rate = new_stock_value / new_stock_qty if not self.valuation_rate and sle.voucher_detail_no: allow_zero_rate = self.check_if_allow_zero_valuation_rate( sle.voucher_type, sle.voucher_detail_no) if not allow_zero_rate: self.valuation_rate = get_valuation_rate( sle.item_code, sle.warehouse, sle.voucher_type, sle.voucher_no, self.allow_zero_rate, currency=erpnext.get_company_currency(sle.company))
def get_incoming_rate(args): """Get Incoming Rate based on valuation method""" if isinstance(args, basestring): args = json.loads(args) in_rate = 0 batch_wise_rate = cint( frappe.db.get_single_value( "Stock Settings", 'exact_cost_valuation_for_batch_wise_items')) if args.get("batch_no") and batch_wise_rate: in_rate = get_batch_rate(args.get("batch_no")) elif (args.get("serial_no") or "").strip(): in_rate = get_avg_purchase_rate(args.get("serial_no")) else: valuation_method = get_valuation_method(args.get("item_code")) previous_sle = get_previous_sle(args) if valuation_method == 'FIFO': if previous_sle: previous_stock_queue = json.loads( previous_sle.get('stock_queue', '[]') or '[]') in_rate = get_fifo_rate(previous_stock_queue, args.get("qty") or 0) if previous_stock_queue else 0 elif valuation_method == 'Moving Average': in_rate = previous_sle.get('valuation_rate') or 0 if not in_rate: voucher_no = args.get('voucher_no') or args.get('name') in_rate = get_valuation_rate(args.get('item_code'), args.get('warehouse'), args.get('voucher_type'), voucher_no, args.get('allow_zero_valuation'), currency=erpnext.get_company_currency( args.get('company')), company=args.get('company')) return in_rate
def get_incoming_rate(args, raise_error_if_no_rate=True): """Get Incoming Rate based on valuation method""" from erpnext.stock.stock_ledger import get_previous_sle, get_valuation_rate if isinstance(args, string_types): args = json.loads(args) in_rate = 0 if (args.get("serial_no") or "").strip(): in_rate = get_avg_purchase_rate(args.get("serial_no")) else: valuation_method = get_valuation_method(args.get("item_code")) previous_sle = get_previous_sle(args) if valuation_method == "FIFO": if previous_sle: previous_stock_queue = json.loads( previous_sle.get("stock_queue", "[]") or "[]") in_rate = (get_fifo_rate(previous_stock_queue, args.get("qty") or 0) if previous_stock_queue else 0) elif valuation_method == "Moving Average": in_rate = previous_sle.get("valuation_rate") or 0 if not in_rate: voucher_no = args.get("voucher_no") or args.get("name") in_rate = get_valuation_rate( args.get("item_code"), args.get("warehouse"), args.get("voucher_type"), voucher_no, args.get("allow_zero_valuation"), currency=erpnext.get_company_currency(args.get("company")), company=args.get("company"), raise_error_if_no_rate=raise_error_if_no_rate, ) return flt(in_rate)
def update_raw_materials_supplied_based_on_bom(self, item, raw_material_table): exploded_item = 1 if hasattr(item, 'include_exploded_items'): exploded_item = item.get('include_exploded_items') bom_items = get_items_from_bom(item.item_code, item.bom, exploded_item) used_alternative_items = [] if self.doctype == 'Purchase Receipt' and item.purchase_order: used_alternative_items = get_used_alternative_items( purchase_order=item.purchase_order) raw_materials_cost = 0 items = list(set([d.item_code for d in bom_items])) item_wh = frappe._dict( frappe.db.sql( """select i.item_code, id.default_warehouse from `tabItem` i, `tabItem Default` id where id.parent=i.name and id.company=%s and i.name in ({0})""".format( ", ".join(["%s"] * len(items))), [self.company] + items)) for bom_item in bom_items: if self.doctype == "Purchase Order": reserve_warehouse = bom_item.source_warehouse or item_wh.get( bom_item.item_code) if frappe.db.get_value("Warehouse", reserve_warehouse, "company") != self.company: reserve_warehouse = None conversion_factor = item.conversion_factor if (self.doctype == 'Purchase Receipt' and item.purchase_order and bom_item.item_code in used_alternative_items): alternative_item_data = used_alternative_items.get( bom_item.item_code) bom_item.item_code = alternative_item_data.item_code bom_item.item_name = alternative_item_data.item_name bom_item.stock_uom = alternative_item_data.stock_uom conversion_factor = alternative_item_data.conversion_factor bom_item.description = alternative_item_data.description # check if exists exists = 0 for d in self.get(raw_material_table): if d.main_item_code == item.item_code and d.rm_item_code == bom_item.item_code \ and d.reference_name == item.name: rm, exists = d, 1 break if not exists: rm = self.append(raw_material_table, {}) required_qty = flt( flt(bom_item.qty_consumed_per_unit) * (flt(item.qty) + getattr(item, 'rejected_qty', 0)) * flt(conversion_factor), rm.precision("required_qty")) rm.reference_name = item.name rm.bom_detail_no = bom_item.name rm.main_item_code = item.item_code rm.rm_item_code = bom_item.item_code rm.stock_uom = bom_item.stock_uom rm.required_qty = required_qty if self.doctype == "Purchase Order" and not rm.reserve_warehouse: rm.reserve_warehouse = reserve_warehouse rm.conversion_factor = conversion_factor if self.doctype in ["Purchase Receipt", "Purchase Invoice"]: rm.consumed_qty = required_qty rm.description = bom_item.description if item.batch_no and not rm.batch_no: rm.batch_no = item.batch_no # get raw materials rate if self.doctype == "Purchase Receipt": from erpnext.stock.utils import get_incoming_rate rm.rate = get_incoming_rate({ "item_code": bom_item.item_code, "warehouse": self.supplier_warehouse, "posting_date": self.posting_date, "posting_time": self.posting_time, "qty": -1 * required_qty, "serial_no": rm.serial_no }) if not rm.rate: rm.rate = get_valuation_rate( bom_item.item_code, self.supplier_warehouse, self.doctype, self.name, currency=self.company_currency, company=self.company) else: rm.rate = bom_item.rate rm.amount = required_qty * flt(rm.rate) raw_materials_cost += flt(rm.amount) if self.doctype in ("Purchase Receipt", "Purchase Invoice"): item.rm_supp_cost = raw_materials_cost
def update_raw_materials_supplied_based_on_bom(self, item, raw_material_table): exploded_item = 1 if hasattr(item, 'include_exploded_items'): exploded_item = item.get('include_exploded_items') bom_items = get_items_from_bom(item.item_code, item.bom, exploded_item) used_alternative_items = [] if self.doctype == 'Purchase Receipt' and item.purchase_order: used_alternative_items = get_used_alternative_items(purchase_order = item.purchase_order) raw_materials_cost = 0 items = list(set([d.item_code for d in bom_items])) item_wh = frappe._dict(frappe.db.sql("""select i.item_code, id.default_warehouse from `tabItem` i, `tabItem Default` id where id.parent=i.name and id.company=%s and i.name in ({0})""" .format(", ".join(["%s"] * len(items))), [self.company] + items)) for bom_item in bom_items: if self.doctype == "Purchase Order": reserve_warehouse = bom_item.source_warehouse or item_wh.get(bom_item.item_code) if frappe.db.get_value("Warehouse", reserve_warehouse, "company") != self.company: reserve_warehouse = None conversion_factor = item.conversion_factor if (self.doctype == 'Purchase Receipt' and item.purchase_order and bom_item.item_code in used_alternative_items): alternative_item_data = used_alternative_items.get(bom_item.item_code) bom_item.item_code = alternative_item_data.item_code bom_item.item_name = alternative_item_data.item_name bom_item.stock_uom = alternative_item_data.stock_uom conversion_factor = alternative_item_data.conversion_factor bom_item.description = alternative_item_data.description # check if exists exists = 0 for d in self.get(raw_material_table): if d.main_item_code == item.item_code and d.rm_item_code == bom_item.item_code \ and d.reference_name == item.name: rm, exists = d, 1 break if not exists: rm = self.append(raw_material_table, {}) required_qty = flt(flt(bom_item.qty_consumed_per_unit) * (flt(item.qty) + getattr(item, 'rejected_qty', 0)) * flt(conversion_factor), rm.precision("required_qty")) rm.reference_name = item.name rm.bom_detail_no = bom_item.name rm.main_item_code = item.item_code rm.rm_item_code = bom_item.item_code rm.stock_uom = bom_item.stock_uom rm.required_qty = required_qty if self.doctype == "Purchase Order" and not rm.reserve_warehouse: rm.reserve_warehouse = reserve_warehouse rm.conversion_factor = conversion_factor if self.doctype in ["Purchase Receipt", "Purchase Invoice"]: rm.consumed_qty = required_qty rm.description = bom_item.description if item.batch_no and not rm.batch_no: rm.batch_no = item.batch_no # get raw materials rate if self.doctype == "Purchase Receipt": from erpnext.stock.utils import get_incoming_rate rm.rate = get_incoming_rate({ "item_code": bom_item.item_code, "warehouse": self.supplier_warehouse, "posting_date": self.posting_date, "posting_time": self.posting_time, "qty": -1 * required_qty, "serial_no": rm.serial_no }) if not rm.rate: rm.rate = get_valuation_rate(bom_item.item_code, self.supplier_warehouse, self.doctype, self.name, currency=self.company_currency, company = self.company) else: rm.rate = bom_item.rate rm.amount = required_qty * flt(rm.rate) raw_materials_cost += flt(rm.amount) if self.doctype in ("Purchase Receipt", "Purchase Invoice"): item.rm_supp_cost = raw_materials_cost
def update_raw_materials_supplied(self, item, raw_material_table): bom_items = self.get_items_from_bom(item.item_code, item.bom) raw_materials_cost = 0 items = list(set([d.item_code for d in bom_items])) item_wh = frappe._dict( frappe.db.sql( """select item_code, default_warehouse from `tabItem` where name in ({0})""".format(", ".join(["%s"] * len(items))), items)) for bom_item in bom_items: if self.doctype == "Purchase Order": reserve_warehouse = bom_item.source_warehouse or item_wh.get( bom_item.item_code) if frappe.db.get_value("Warehouse", reserve_warehouse, "company") != self.company: reserve_warehouse = None # check if exists exists = 0 for d in self.get(raw_material_table): if d.main_item_code == item.item_code and d.rm_item_code == bom_item.item_code \ and d.reference_name == item.name: rm, exists = d, 1 break if not exists: rm = self.append(raw_material_table, {}) required_qty = flt( flt(bom_item.qty_consumed_per_unit) * flt(item.qty) * flt(item.conversion_factor), rm.precision("required_qty")) rm.reference_name = item.name rm.bom_detail_no = bom_item.name rm.main_item_code = item.item_code rm.rm_item_code = bom_item.item_code rm.stock_uom = bom_item.stock_uom rm.required_qty = required_qty if self.doctype == "Purchase Order" and not rm.reserve_warehouse: rm.reserve_warehouse = reserve_warehouse rm.conversion_factor = item.conversion_factor if self.doctype in ["Purchase Receipt", "Purchase Invoice"]: rm.consumed_qty = required_qty rm.description = bom_item.description if item.batch_no and not rm.batch_no: rm.batch_no = item.batch_no # get raw materials rate if self.doctype == "Purchase Receipt": from erpnext.stock.utils import get_incoming_rate rm.rate = get_incoming_rate({ "item_code": bom_item.item_code, "warehouse": self.supplier_warehouse, "posting_date": self.posting_date, "posting_time": self.posting_time, "qty": -1 * required_qty, "serial_no": rm.serial_no }) if not rm.rate: rm.rate = get_valuation_rate( bom_item.item_code, self.supplier_warehouse, self.doctype, self.name, currency=self.company_currency, company=self.company) else: rm.rate = bom_item.rate rm.amount = required_qty * flt(rm.rate) raw_materials_cost += flt(rm.amount) if self.doctype in ("Purchase Receipt", "Purchase Invoice"): item.rm_supp_cost = raw_materials_cost
def update_raw_materials_supplied(self, item, raw_material_table): bom_items = self.get_items_from_bom(item.item_code, item.bom) raw_materials_cost = 0 items = list(set([d.item_code for d in bom_items])) item_wh = frappe._dict(frappe.db.sql("""select item_code, default_warehouse from `tabItem` where name in ({0})""".format(", ".join(["%s"] * len(items))), items)) for bom_item in bom_items: if self.doctype == "Purchase Order": reserve_warehouse = bom_item.source_warehouse or item_wh.get(bom_item.item_code) if frappe.db.get_value("Warehouse", reserve_warehouse, "company") != self.company: reserve_warehouse = None # check if exists exists = 0 for d in self.get(raw_material_table): if d.main_item_code == item.item_code and d.rm_item_code == bom_item.item_code \ and d.reference_name == item.name: rm, exists = d, 1 break if not exists: rm = self.append(raw_material_table, {}) required_qty = flt(flt(bom_item.qty_consumed_per_unit) * flt(item.qty) * flt(item.conversion_factor), rm.precision("required_qty")) rm.reference_name = item.name rm.bom_detail_no = bom_item.name rm.main_item_code = item.item_code rm.rm_item_code = bom_item.item_code rm.stock_uom = bom_item.stock_uom rm.required_qty = required_qty if self.doctype == "Purchase Order" and not rm.reserve_warehouse: rm.reserve_warehouse = reserve_warehouse rm.conversion_factor = item.conversion_factor if self.doctype in ["Purchase Receipt", "Purchase Invoice"]: rm.consumed_qty = required_qty rm.description = bom_item.description if item.batch_no and not rm.batch_no: rm.batch_no = item.batch_no # get raw materials rate if self.doctype == "Purchase Receipt": from erpnext.stock.utils import get_incoming_rate rm.rate = get_incoming_rate({ "item_code": bom_item.item_code, "warehouse": self.supplier_warehouse, "posting_date": self.posting_date, "posting_time": self.posting_time, "qty": -1 * required_qty, "serial_no": rm.serial_no }) if not rm.rate: rm.rate = get_valuation_rate(bom_item.item_code, self.supplier_warehouse, self.doctype, self.name, currency=self.company_currency, company = self.company) else: rm.rate = bom_item.rate rm.amount = required_qty * flt(rm.rate) raw_materials_cost += flt(rm.amount) if self.doctype in ("Purchase Receipt", "Purchase Invoice"): item.rm_supp_cost = raw_materials_cost