def test_reserved_qty_for_production_on_stock_entry(self): test_stock_entry.make_stock_entry(item_code="_Test Item", target= self.warehouse, qty=100, basic_rate=100) test_stock_entry.make_stock_entry(item_code="_Test Item Home Desktop 100", target= self.warehouse, qty=100, basic_rate=100) self.test_reserved_qty_for_production_submit() s = frappe.get_doc(make_stock_entry(self.pro_order.name, "Material Transfer for Manufacture", 2)) s.submit() bin1_on_start_production = get_bin(self.item, self.warehouse) # reserved_qty_for_producion updated self.assertEqual(cint(self.bin1_at_start.reserved_qty_for_production), cint(bin1_on_start_production.reserved_qty_for_production)) # projected qty will now be 2 less (becuase of item movement) self.assertEqual(cint(self.bin1_at_start.projected_qty), cint(bin1_on_start_production.projected_qty) + 2) s = frappe.get_doc(make_stock_entry(self.pro_order.name, "Manufacture", 2)) bin1_on_end_production = get_bin(self.item, self.warehouse) # no change in reserved / projected self.assertEqual(cint(bin1_on_end_production.reserved_qty_for_production), cint(bin1_on_start_production.reserved_qty_for_production)) self.assertEqual(cint(bin1_on_end_production.projected_qty), cint(bin1_on_end_production.projected_qty))
def update_item_stock(item_code, shopify_settings, bin=None): item = frappe.get_doc("Item", item_code) if item.sync_qty_with_shopify: if not bin: bin = get_bin(item_code, shopify_settings.warehouse) if not item.shopify_product_id and not item.variant_of: sync_item_with_shopify(item, shopify_settings.price_list, shopify_settings.warehouse) if item.sync_with_shopify and item.shopify_product_id and shopify_settings.warehouse == bin.warehouse: if item.variant_of: item_data, resource = get_product_update_dict_and_resource(frappe.get_value("Item", item.variant_of, "shopify_product_id"), item.shopify_variant_id) else: item_data, resource = get_product_update_dict_and_resource(item.shopify_product_id, item.shopify_variant_id) item_data["product"]["variants"][0].update({ "inventory_quantity": cint(bin.actual_qty), "inventory_management": "shopify" }) try: put_request(resource, item_data) except requests.exceptions.HTTPError, e: if e.args[0] and e.args[0].startswith("404"): disable_shopify_sync_for_item(item) else: raise e
def test_reserved_qty_for_production_submit(self): self.bin1_at_start = get_bin(self.item, self.warehouse) # reset to correct value self.bin1_at_start.update_reserved_qty_for_production() self.pro_order = make_prod_order_test_record(item="_Test FG Item", qty=2, source_warehouse=self.warehouse) self.bin1_on_submit = get_bin(self.item, self.warehouse) # reserved qty for production is updated self.assertEqual( cint(self.bin1_at_start.reserved_qty_for_production) + 2, cint(self.bin1_on_submit.reserved_qty_for_production), ) self.assertEqual(cint(self.bin1_at_start.projected_qty), cint(self.bin1_on_submit.projected_qty) + 2)
def update_item_stock(item_code, shopify_settings, bin=None): item = frappe.get_doc("Item", item_code) if item.sync_qty_with_shopify: if not bin: bin = get_bin(item_code, shopify_settings.warehouse) if not item.shopify_product_id and not item.variant_of: sync_item_with_shopify(item, shopify_settings.price_list, shopify_settings.warehouse) if item.sync_with_shopify and item.shopify_product_id and shopify_settings.warehouse == bin.warehouse: if item.variant_of: item_data, resource = get_product_update_dict_and_resource(frappe.get_value("Item", item.variant_of, "shopify_product_id"), item.shopify_variant_id, is_variant=True, actual_qty=bin.actual_qty) else: item_data, resource = get_product_update_dict_and_resource(item.shopify_product_id, item.shopify_variant_id, actual_qty=bin.actual_qty) try: put_request(resource, item_data) except requests.exceptions.HTTPError as e: if e.args[0] and e.args[0].startswith("404"): make_shopify_log(title=e.message, status="Error", method="sync_shopify_items", message=frappe.get_traceback(), request_data=item_data, exception=True) disable_shopify_sync_for_item(item) else: raise e
def _update_requested_qty(item_code, warehouse): requested_qty = frappe.db.sql("""select sum(mr_item.qty - ifnull(mr_item.ordered_qty, 0)) from `tabMaterial Request Item` mr_item, `tabMaterial Request` mr where mr_item.item_code=%s and mr_item.warehouse=%s and mr_item.qty > ifnull(mr_item.ordered_qty, 0) and mr_item.parent=mr.name and mr.status!='Stopped' and mr.docstatus=1""", (item_code, warehouse)) bin_doc = get_bin(item_code, warehouse) bin_doc.indented_qty = flt(requested_qty[0][0]) if requested_qty else 0 bin_doc.save()
def update_reserved_qty_for_production(self, items=None): '''update reserved_qty_for_production in bins''' if not self.source_warehouse: return if not items: items = [d.item_code for d in self.required_items] for item in items: stock_bin = get_bin(item, self.source_warehouse) stock_bin.update_reserved_qty_for_production()
def _update_ordered_qty(item_code, warehouse): ordered_qty = frappe.db.sql(""" select sum((po_item.qty - ifnull(po_item.received_qty, 0))*po_item.conversion_factor) from `tabPurchase Order Item` po_item, `tabPurchase Order` po where po_item.item_code=%s and po_item.warehouse=%s and po_item.qty > ifnull(po_item.received_qty, 0) and po_item.parent=po.name and po.status!='Stopped' and po.docstatus=1""", (item_code, warehouse)) bin_doc = get_bin(item_code, warehouse) bin_doc.ordered_qty = flt(ordered_qty[0][0]) if ordered_qty else 0 bin_doc.save()
def test_reserved_qty_for_production_cancel(self): self.test_reserved_qty_for_production_submit() self.pro_order.cancel() bin1_on_cancel = get_bin(self.item, self.warehouse) # reserved_qty_for_producion updated self.assertEqual( cint(self.bin1_at_start.reserved_qty_for_production), cint(bin1_on_cancel.reserved_qty_for_production) ) self.assertEqual(self.bin1_at_start.projected_qty, cint(bin1_on_cancel.projected_qty))
def test_projected_qty_for_production_and_sales_order(self): before_production_order = get_bin(self.item, self.warehouse) before_production_order.update_reserved_qty_for_production() self.pro_order = make_prod_order_test_record(item="_Test FG Item", qty=2, source_warehouse=self.warehouse) after_production_order = get_bin(self.item, self.warehouse) sales_order = make_sales_order(item=self.item, qty=2) after_sales_order = get_bin(self.item, self.warehouse) self.assertEqual( cint(before_production_order.reserved_qty_for_production) + 2, cint(after_sales_order.reserved_qty_for_production), ) self.assertEqual(cint(before_production_order.projected_qty), cint(after_sales_order.projected_qty) + 2) total_projected_qty = get_total_projected_qty(self.item) item_doc = frappe.get_doc("Item", self.item) self.assertEqual(total_projected_qty, item_doc.total_projected_qty)
def update_purchase_order_supplied_items(self): #Get PO Supplied Items Details item_wh = frappe._dict(frappe.db.sql(""" select rm_item_code, reserve_warehouse from `tabPurchase Order` po, `tabPurchase Order Item Supplied` poitemsup where po.name = poitemsup.parent and po.name = %s""", self.purchase_order)) #Update reserved sub contracted quantity in bin based on Supplied Item Details for d in self.get("items"): reserve_warehouse = item_wh.get(d.item_code) stock_bin = get_bin(d.item_code, reserve_warehouse) stock_bin.update_reserved_qty_for_sub_contracting()
def update_bin_qty(item_code, warehouse, qty_dict=None): from erpnext.stock.utils import get_bin bin = get_bin(item_code, warehouse) mismatch = False for fld, val in qty_dict.items(): if flt(bin.get(fld)) != flt(val): bin.set(fld, flt(val)) mismatch = True if mismatch: bin.set_projected_qty() bin.db_update() bin.clear_cache()
def update_bin_qty(item_code, warehouse, qty_dict=None): from erpnext.stock.utils import get_bin bin = get_bin(item_code, warehouse) mismatch = False for fld, val in qty_dict.items(): if flt(bin.get(fld)) != flt(val): bin.set(fld, flt(val)) mismatch = True if mismatch: bin.projected_qty = flt(bin.actual_qty) + flt(bin.ordered_qty) + \ flt(bin.indented_qty) + flt(bin.planned_qty) - flt(bin.reserved_qty) bin.save()
def execute(): frappe.reload_doc("stock", "doctype", "bin") frappe.reload_doc("buying", "doctype", "purchase_order_item_supplied") for d in frappe.db.sql(""" select distinct rm_item_code, reserve_warehouse from `tabPurchase Order Item Supplied` where docstatus=1 and reserve_warehouse is not null and reserve_warehouse != ''"""): try: bin_doc = get_bin(d[0], d[1]) bin_doc.update_reserved_qty_for_sub_contracting() except: pass for d in frappe.db.sql("""select distinct item_code, source_warehouse from `tabWork Order Item` where docstatus=1 and transferred_qty > required_qty and source_warehouse is not null and source_warehouse != ''""", as_list=1): try: bin_doc = get_bin(d[0], d[1]) bin_doc.update_reserved_qty_for_production() except: pass
def test_reserved_qty_for_production_on_stock_entry(self): test_stock_entry.make_stock_entry(item_code="_Test Item", target= self.warehouse, qty=100, basic_rate=100) test_stock_entry.make_stock_entry(item_code="_Test Item Home Desktop 100", target= self.warehouse, qty=100, basic_rate=100) self.test_reserved_qty_for_production_submit() s = frappe.get_doc(make_stock_entry(self.pro_order.name, "Material Transfer for Manufacture", 2)) s.submit() bin1_on_start_production = get_bin(self.item, self.warehouse) # reserved_qty_for_producion updated self.assertEqual(cint(self.bin1_at_start.reserved_qty_for_production), cint(bin1_on_start_production.reserved_qty_for_production)) # projected qty will now be 2 less (becuase of item movement) self.assertEqual(cint(self.bin1_at_start.projected_qty), cint(bin1_on_start_production.projected_qty) + 2) s = frappe.get_doc(make_stock_entry(self.pro_order.name, "Manufacture", 2)) bin1_on_end_production = get_bin(self.item, self.warehouse) # no change in reserved / projected self.assertEqual(cint(bin1_on_end_production.reserved_qty_for_production), cint(bin1_on_start_production.reserved_qty_for_production)) self.assertEqual(cint(bin1_on_end_production.projected_qty), cint(bin1_on_end_production.projected_qty)) # required_items removed self.pro_order.reload() self.assertEqual(len(self.pro_order.required_items), 0)
def update_bin_qty(item_code, warehouse, qty_dict=None): from erpnext.stock.utils import get_bin bin = get_bin(item_code, warehouse) mismatch = False for field, value in qty_dict.items(): if flt(bin.get(field)) != flt(value): bin.set(field, flt(value)) mismatch = True bin.modified = now() if mismatch: bin.set_projected_qty() bin.db_update() bin.clear_cache()
def update_bin_qty(item_code, warehouse, qty_dict=None): from erpnext.stock.utils import get_bin bin = get_bin(item_code, warehouse) mismatch = False for fld, val in qty_dict.items(): if flt(bin.get(fld)) != flt(val): bin.set(fld, flt(val)) mismatch = True if mismatch: bin.projected_qty = (flt(bin.actual_qty) + flt(bin.ordered_qty) + flt(bin.indented_qty) + flt(bin.planned_qty) - flt(bin.reserved_qty) - flt(bin.reserved_qty_for_production)) - flt(bin.reserved_qty_for_sub_contract) bin.save()
def delete_and_patch_duplicate_bins(): duplicate_bins = frappe.db.sql( """ SELECT item_code, warehouse, count(*) as bin_count FROM tabBin GROUP BY item_code, warehouse HAVING bin_count > 1 """, as_dict=1, ) for duplicate_bin in duplicate_bins: item_code = duplicate_bin.item_code warehouse = duplicate_bin.warehouse existing_bins = frappe.get_list( "Bin", filters={ "item_code": item_code, "warehouse": warehouse }, fields=["name"], order_by="creation", ) # keep last one existing_bins.pop() for broken_bin in existing_bins: frappe.delete_doc("Bin", broken_bin.name) qty_dict = { "reserved_qty": get_reserved_qty(item_code, warehouse), "indented_qty": get_indented_qty(item_code, warehouse), "ordered_qty": get_ordered_qty(item_code, warehouse), "planned_qty": get_planned_qty(item_code, warehouse), "actual_qty": get_balance_qty_from_sle(item_code, warehouse), } bin = get_bin(item_code, warehouse) bin.update(qty_dict) bin.update_reserved_qty_for_production() bin.update_reserved_qty_for_sub_contracting() bin.db_update()
def execute(): po_item = list( frappe.db.sql((""" select distinct po.name as poname, poitem.rm_item_code as rm_item_code, po.company from `tabPurchase Order` po, `tabPurchase Order Item Supplied` poitem where po.name = poitem.parent and po.is_subcontracted = "Yes" and po.docstatus = 1"""), as_dict=1)) if not po_item: return frappe.reload_doc("buying", "doctype", "purchase_order_item_supplied") company_warehouse = frappe._dict( frappe.db.sql("""select company, min(name) from `tabWarehouse` where is_group = 0 group by company""")) items = list(set([d.rm_item_code for d in po_item])) item_wh = frappe._dict( frappe.db.sql( """select item_code, default_warehouse from `tabItem` where name in ({0})""".format(", ".join(["%s"] * len(items))), items)) # Update reserved warehouse for item in po_item: reserve_warehouse = get_warehouse(item.rm_item_code, item.company, company_warehouse, item_wh) update_res_warehouse = frappe.db.sql( """update `tabPurchase Order Item Supplied` set reserve_warehouse = %s where parent = %s and rm_item_code = %s """, (reserve_warehouse, item["poname"], item["rm_item_code"])) # Update bin item_wh_bin = frappe.db.sql((""" select distinct poitemsup.rm_item_code as rm_item_code, poitemsup.reserve_warehouse as reserve_warehouse from `tabPurchase Order` po, `tabPurchase Order Item Supplied` poitemsup where po.name = poitemsup.parent and po.is_subcontracted = "Yes" and po.docstatus = 1"""), as_dict=1) for d in item_wh_bin: stock_bin = get_bin(d["rm_item_code"], d["reserve_warehouse"]) stock_bin.update_reserved_qty_for_sub_contracting()
def execute(): wo = frappe.qb.DocType("Work Order") wo_item = frappe.qb.DocType("Work Order Item") incorrect_item_wh = (frappe.qb.from_(wo).join(wo_item).on( wo.name == wo_item.parent).select( wo_item.item_code, wo.source_warehouse).distinct().where((wo.status == "Closed") & ( wo.docstatus == 1) & (wo.source_warehouse.notnull()))).run() for item_code, warehouse in incorrect_item_wh: if not (item_code and warehouse): continue bin = get_bin(item_code, warehouse) bin.update_reserved_qty_for_production()
def update_item_stock(item_code, magento_settings, bin_doc=None): item = frappe.get_doc("Item", item_code) if item.sync_qty_with_magento: # Si no existe una entrada de inventario, la crea if not bin_doc: bin_doc = get_bin(item_code, magento_settings.warehouse) # Si el item es BASE y no esta SINCRONIZADO (Revisar el Flow) if item.magento_product_id == "No Sync" and not item.variant_of: sync_item_with_magento(item, magento_settings.price_list, magento_settings.warehouse) # Si el item se va a sincronizar, tiene id de de Meli y coincide con el almacen de Meli if item.sync_with_magento and item.magento_product_id and magento_settings.warehouse == bin_doc.warehouse: resource = "/items/{0}".format(item.magento_product_id) # Es un item variante? if item.variant_of: item_data = { "variations": [{ "id": item.magento_variant_id, "available_quantity": cint(bin_doc.actual_qty) }] } if cint(bin_doc.actual_qty) == 0: pass # put_request("/items/{0}".format(item.magento_product_id), {"available_quantity": 1, "status": "paused"}) # item.magento_actual_status = "Pausado" # Es un item simple? else: item_data = {"available_quantity": cint(bin_doc.actual_qty)} try: put_request(resource, item_data) except requests.exceptions.HTTPError, e: if e.args[0] and e.args[0].startswith( "404") or e.args[0].startswith("403"): disable_magento_sync_for_item(item) else: raise e
def update_bin_batch(self): coil_bin = get_bin(self.required_item, self.s_warehouse) if self.batch_qty != coil_bin.projected_qty: frappe.throw('Batch available quantity is: {0} kg'.format( coil_bin.projected_qty)) update_projected_qty(self.required_item, self.s_warehouse, None, None, self.allocate_quantity) update_projected_qty(self.required_item, self.wip_warehouse, self.allocate_quantity, None, self.allocate_quantity) batch = frappe.get_doc('Batch', self.batch_no) s_batch_qty = get_batch_qty(self.batch_no, self.s_warehouse) s_reserved_qty = coil_bin.reserved_qty_for_production available_batch_qty = s_batch_qty - s_reserved_qty if available_batch_qty == 0: batch.db_set('batch_stock_status', 'Empty')
def execute(): po_item = list(frappe.db.sql((""" select distinct po.name as poname, poitem.rm_item_code as rm_item_code, po.company from `tabPurchase Order` po, `tabPurchase Order Item Supplied` poitem where po.name = poitem.parent and po.is_subcontracted = "Yes" and po.docstatus = 1"""), as_dict=1)) if not po_item: return frappe.reload_doc("stock", "doctype", "bin") frappe.reload_doc("buying", "doctype", "purchase_order_item_supplied") company_warehouse = frappe._dict(frappe.db.sql("""select company, min(name) from `tabWarehouse` where is_group = 0 group by company""")) items = list(set([d.rm_item_code for d in po_item])) item_wh = frappe._dict(frappe.db.sql("""select item_code, default_warehouse from `tabItem` where name in ({0})""".format(", ".join(["%s"] * len(items))), items)) # Update reserved warehouse for item in po_item: reserve_warehouse = get_warehouse(item.rm_item_code, item.company, company_warehouse, item_wh) frappe.db.sql("""update `tabPurchase Order Item Supplied` set reserve_warehouse = %s where parent = %s and rm_item_code = %s """, (reserve_warehouse, item["poname"], item["rm_item_code"])) # Update bin item_wh_bin = frappe.db.sql((""" select distinct poitemsup.rm_item_code as rm_item_code, poitemsup.reserve_warehouse as reserve_warehouse from `tabPurchase Order` po, `tabPurchase Order Item Supplied` poitemsup where po.name = poitemsup.parent and po.is_subcontracted = "Yes" and po.docstatus = 1"""), as_dict=1) for d in item_wh_bin: try: stock_bin = get_bin(d["rm_item_code"], d["reserve_warehouse"]) stock_bin.update_reserved_qty_for_sub_contracting() except: pass
def update_projected_qty(item_code, warehouse, indented_qty, planned_qty, reserved_qty_for_production): pwo_bin = get_bin(item_code, warehouse) # Dealing with None variables if indented_qty == None: if pwo_bin.indented_qty == None: pwo_bin.db_set("indented_qty", 0) else: if pwo_bin.indented_qty == None: pwo_bin.db_set("indented_qty", 0) indented_qty += round(pwo_bin.indented_qty, 2) pwo_bin.db_set("indented_qty", round(indented_qty, 2)) if planned_qty == None: if pwo_bin.planned_qty == None: pwo_bin.db_set("planned_qty", 0) else: if pwo_bin.planned_qty == None: pwo_bin.db_set("planned_qty", 0) planned_qty += round(pwo_bin.planned_qty, 2) pwo_bin.db_set("planned_qty", round(planned_qty, 2)) if reserved_qty_for_production == None: if pwo_bin.reserved_qty_for_production == None: pwo_bin.db_set("reserved_qty_for_production", 0) else: if pwo_bin.reserved_qty_for_production == None: pwo_bin.db_set("reserved_qty_for_production", 0) reserved_qty_for_production += round( pwo_bin.reserved_qty_for_production, 2) pwo_bin.db_set("reserved_qty_for_production", round(reserved_qty_for_production, 2)) new_projected_qty = pwo_bin.actual_qty+ \ pwo_bin.ordered_qty+ \ pwo_bin.indented_qty+ \ pwo_bin.planned_qty- \ pwo_bin.reserved_qty- \ pwo_bin.reserved_qty_for_production pwo_bin.db_set("projected_qty", new_projected_qty)
def init_bin(item, warehouse): pwo_bin = get_bin(item, warehouse) if pwo_bin.reserved_qty == None: pwo_bin.db_set("reserved_qty", 0) if pwo_bin.actual_qty == None: pwo_bin.db_set("actual_qty", 0) if pwo_bin.ordered_qty == None: pwo_bin.db_set("ordered_qty", 0) if pwo_bin.indented_qty == None: pwo_bin.db_set("indented_qty", 0) if pwo_bin.planned_qty == None: pwo_bin.db_set("planned_qty", 0) if pwo_bin.projected_qty == None: pwo_bin.db_set("projected_qty", 0) if pwo_bin.reserved_qty_for_production == None: pwo_bin.db_set("reserved_qty_for_production", 0) if pwo_bin.reserved_qty_for_sub_contract == None: pwo_bin.db_set("reserved_qty_for_sub_contract", 0) if pwo_bin.valuation_rate == None: pwo_bin.db_set("valuation_rate", 0) if pwo_bin.stock_value == None: pwo_bin.db_set("stock_value", 0)
def update_item_stock(item_code, shopify_settings, bin=None): item = frappe.get_doc("Item", item_code) if item.sync_qty_with_shopify: if not bin: bin = get_bin(item_code, shopify_settings.warehouse) if not item.shopify_product_id and not item.variant_of: sync_item_with_shopify(item, shopify_settings.price_list, shopify_settings.warehouse) if item.sync_with_shopify and item.shopify_product_id and shopify_settings.warehouse == bin.warehouse: if item.variant_of: item_data, resource = get_product_update_dict_and_resource(frappe.get_value("Item", item.variant_of, "shopify_product_id"), item.shopify_variant_id) else: item_data, resource = get_product_update_dict_and_resource(item.shopify_product_id, item.shopify_variant_id) item_data["product"]["variants"][0].update({ "inventory_quantity": cint(bin.actual_qty), "inventory_management": "shopify" }) put_request(resource, item_data)
def set_pwo_status(pipes_work_order, status): pwo = frappe.get_doc("Pipes Work Order", pipes_work_order) if status == "Stopped": pwo.db_set("status", status) return "stopped" else: produced_qty_weight = round(pwo.produced_qty * pwo.weight, 2) passed_qty_weight = round( pwo.weight * (pwo.no_of_a_quality_pipes + pwo.no_of_b_quality_pipes), 2) total_scrap_weight = round( pwo.pipe_jala_bora + pwo.phakra_pipe + pwo.bari_end_cut, 2) total_weight_produced = produced_qty_weight + total_scrap_weight total_weight_produced = round(total_weight_produced, 1) total_weight_processed = passed_qty_weight + total_scrap_weight total_weight_processed = round(total_weight_processed, 1) #if status == 'Resumed': if pwo.produced_qty == 0 and pwo.mtf_manufacturing == 0: status = "Started" elif pwo.mtf_manufacturing > 0 and pwo.mtf_manufacturing != pwo.total_required_material: status = "Material Partially Transfered" elif pwo.mtf_manufacturing == pwo.total_required_material and pwo.total_required_material != total_weight_produced: status = "In Process" elif pwo.total_required_material != total_weight_processed: status = "Quality Inspection" elif pwo.total_required_material == total_weight_processed: status = "Completed" pwo.db_set("actual_end_date", get_datetime()) pipe_bin = get_bin(pwo.production_item, pwo.t_warehouse) new_pipe_planned_qty = round(pipe_bin.planned_qty) - ( round(pwo.qty, 2) - round(pwo.produced_qty)) new_pipe_planned_qty = round(new_pipe_planned_qty, 2) update_projected_qty(pwo.production_item, pwo.t_warehouse, None, new_pipe_planned_qty, None) pwo.db_set("status", status) pwo.reload() return "resumed"
def update_item_stock(item_code, woocommerce_settings, bin=None): item = frappe.get_doc("Item", item_code) if item.sync_qty_with_woocommerce: if not bin: bin = get_bin(item_code, woocommerce_settings.warehouse) if not item.woocommerce_product_id and not item.variant_of: sync_item_with_woocommerce(item, woocommerce_settings.price_list, woocommerce_settings.warehouse) if item.sync_with_woocommerce and item.woocommerce_product_id and woocommerce_settings.warehouse == bin.warehouse: if item.variant_of: item_data, resource = get_product_update_dict_and_resource( frappe.get_value("Item", item.variant_of, "woocommerce_product_id"), item.woocommerce_variant_id, is_variant=True, actual_qty=bin.actual_qty) else: item_data, resource = get_product_update_dict_and_resource( item.woocommerce_product_id, item.woocommerce_variant_id, actual_qty=bin.actual_qty) try: put_request(resource, item_data) except requests.exceptions.HTTPError, e: if e.args[0] and e.args[0].startswith("404"): make_woocommerce_log(title=e.message, status="Error", method="sync_woocommerce_items", message=frappe.get_traceback(), request_data=item_data, exception=True) disable_woocommerce_sync_for_item(item) else: raise e
def material_manufacture(pipes_work_order, manufacture_qty, status): pwo = frappe.get_doc("Pipes Work Order", pipes_work_order) #weight of item to manufacture total_pipe_weight = round((float(manufacture_qty) * pwo.weight), 2) #Creating new Stock Entry mf = frappe.new_doc("Stock Entry") mf.update({ "stock_entry_type": "Manufacture", "pipes_work_order": pipes_work_order }) #Looping through batches to check if batch qty is enough temp_total_pipe_weight = total_pipe_weight for item in pwo.required_items: if round(temp_total_pipe_weight, 2) != 0 and item.consumed_qty != item.batch_qty: wip_strip_reserved_qty_for_production = 0 #If qty to manufacture == total qty produced + qty to process if ((round(pwo.produced_qty, 2) + round(float(manufacture_qty), 2)) == round(pwo.qty, 2)): if item.batch_qty != item.consumed_qty and item.status == "Transferred": mf.append( "items", { "s_warehouse": pwo.wip_warehouse, "item_code": item.item_code, "qty": item.batch_qty - item.consumed_qty, "batch_no": item.batch_no }) wip_strip = get_bin(item.item_code, pwo.wip_warehouse) wip_strip_reserved_qty_for_production = wip_strip.reserved_qty_for_production - ( item.batch_qty - item.consumed_qty) wip_strip_reserved_qty_for_production = round( wip_strip_reserved_qty_for_production, 2) temp_val = (round((item.batch_qty - item.consumed_qty), 2)) item.db_set("consumed_qty", item.batch_qty) update_projected_qty( item.item_code, pwo.wip_warehouse, None, None, wip_strip_reserved_qty_for_production) #If qty to process is less than batch_qty elif (round((item.batch_qty - item.consumed_qty), 2)) > ( temp_total_pipe_weight) and item.status == "Transferred": mf.append( "items", { "s_warehouse": pwo.wip_warehouse, "item_code": item.item_code, "qty": round(temp_total_pipe_weight, 2), "batch_no": item.batch_no }) temp_batch_qty = round(item.consumed_qty, 2) + round( temp_total_pipe_weight, 2) wip_strip = get_bin(item.item_code, pwo.wip_warehouse) wip_strip_reserved_qty_for_production = wip_strip.reserved_qty_for_production - round( temp_total_pipe_weight, 2) wip_strip_reserved_qty_for_production = round( wip_strip_reserved_qty_for_production, 2) temp_val = (round((item.batch_qty - item.consumed_qty), 2)) item.db_set("consumed_qty", temp_batch_qty) update_projected_qty(item.item_code, pwo.wip_warehouse, None, None, wip_strip_reserved_qty_for_production) temp_total_pipe_weight = 0 #If qty to process is greater than batch_qty elif round( (item.batch_qty - item.consumed_qty), 2 ) < temp_total_pipe_weight and item.status == "Transferred": mf.append( "items", { "s_warehouse": pwo.wip_warehouse, "item_code": item.item_code, "qty": round((item.batch_qty - item.consumed_qty), 2), "batch_no": item.batch_no }) temp_total_pipe_weight = temp_total_pipe_weight - (round( (item.batch_qty - item.consumed_qty), 2)) wip_strip = get_bin(item.item_code, pwo.wip_warehouse) wip_strip_reserved_qty_for_production = wip_strip.reserved_qty_for_production - ( round((item.batch_qty - item.consumed_qty), 2)) wip_strip_reserved_qty_for_production = round( wip_strip_reserved_qty_for_production, 2) temp_val = (round((item.batch_qty - item.consumed_qty), 2)) item.db_set("consumed_qty", item.batch_qty) update_projected_qty(item.item_code, pwo.wip_warehouse, None, None, wip_strip_reserved_qty_for_production) mf.save() temp_manufacture_qty = float(manufacture_qty) temp_basic_rate = round(mf.total_outgoing_value / temp_manufacture_qty, 2) mf.append( "items", { "t_warehouse": pwo.t_warehouse, "item_code": pwo.production_item, "qty": round(float(manufacture_qty), 2), "basic_rate": temp_basic_rate }) mf.save() mf.submit() #Updating PWO produced qty total_producded_qty = pwo.produced_qty + round(float(manufacture_qty), 2) pwo.db_set("produced_qty", total_producded_qty) #Updating Material Request mr_per_ordered = 0 mr_req_qty = 0 mr_received_qty = 0 mr = frappe.get_doc("Material Request", pwo.material_request) for item in mr.items: if item.item_code == pwo.production_item and item.ordered_qty == item.qty and item.ordered_qty != item.received_qty and pwo.req_qty == item.qty: new_received_qty = item.received_qty + round( float(manufacture_qty), 2) item.db_set("received_qty", new_received_qty) mr_per_ordered += item.ordered_qty mr_req_qty += item.qty mr_received_qty += item.received_qty percentage_ordered = (mr_per_ordered) * 100 / mr_req_qty percentage_received = (mr_received_qty) * 100 / mr_req_qty mr.db_set("per_ordered", percentage_ordered) mr.db_set("per_received", percentage_received) if percentage_ordered < 100: mr.db_set("status", "Partially Ordered") elif percentage_ordered == 100 and percentage_received < 100: mr.db_set("status", "Ordered") else: mr.db_set("status", "Manufactured") pipe_bin = get_bin(pwo.production_item, pwo.t_warehouse) new_planned_qty = pipe_bin.planned_qty - round( float(manufacture_qty), 2) #calculating new planned qty update_projected_qty(pwo.production_item, pwo.t_warehouse, None, new_planned_qty, None) #Updating Bin update_pipe_details(pipes_work_order) set_pwo_status(pipes_work_order, status) #Updating Status of PWO
def scrap_trasnfer(pipes_work_order, pipe_jala_bora, phakra_pipe, bari_end_cut): pwo = frappe.get_doc("Pipes Work Order", pipes_work_order) pipe_jala_bora_temp = round(float(pipe_jala_bora), 2) phakra_pipe_temp = round(float(phakra_pipe), 2) bari_end_cut_temp = round(float(bari_end_cut), 2) total_weight = pipe_jala_bora_temp + phakra_pipe_temp + bari_end_cut_temp #Creating new stock entry mf = frappe.new_doc("Stock Entry") mf.update({ "stock_entry_type": "Manufacture", "pipes_work_order": pipes_work_order }) #Looping throw batches total_weight_tmp = total_weight total_remaining_qty_temp = 0 for item in pwo.required_items: if item.status == "Transferred": total_remaining_qty_temp += round( (item.batch_qty - item.consumed_qty), 2) for item in pwo.required_items: if total_weight_tmp != 0 and item.consumed_qty != item.batch_qty: #Consuming all batches if total_weight == total_remaining_qty_temp and item.status == "Transferred": mf.append( "items", { "s_warehouse": pwo.wip_warehouse, "item_code": item.item_code, "qty": round((item.batch_qty - item.consumed_qty), 2), "batch_no": item.batch_no }) total_weight_tmp = total_weight_tmp - (item.batch_qty - item.consumed_qty) total_weight_tmp = round(total_weight_tmp, 2) wip_strip = get_bin(item.item_code, pwo.wip_warehouse) new_wip_strip_reserved_qty_for_production = wip_strip.reserved_qty_for_production - round( (item.batch_qty - item.consumed_qty), 2) new_wip_strip_reserved_qty_for_production = round( new_wip_strip_reserved_qty_for_production, 2) #frappe.msgprint("total scrap weight {0}".format(total_weight_tmp)) temp_val = (round((item.batch_qty - item.consumed_qty), 2)) item.db_set("consumed_qty", item.batch_qty) update_projected_qty( item.item_code, pwo.wip_warehouse, None, None, new_wip_strip_reserved_qty_for_production) #Scrap is less than remaining batch qty elif total_weight_tmp < round((item.batch_qty - item.consumed_qty), 2) and item.status == "Transferred": mf.append( "items", { "s_warehouse": pwo.wip_warehouse, "item_code": item.item_code, "qty": total_weight_tmp, "batch_no": item.batch_no }) temp_batch_qty = round(item.consumed_qty, 2) + total_weight_tmp wip_strip = get_bin(item.item_code, pwo.wip_warehouse) new_wip_strip_reserved_qty_for_production = wip_strip.reserved_qty_for_production - total_weight_tmp temp_val = (round((item.batch_qty - item.consumed_qty), 2)) item.db_set("consumed_qty", temp_batch_qty) update_projected_qty( item.item_code, pwo.wip_warehouse, None, None, new_wip_strip_reserved_qty_for_production) total_weight_tmp = 0 #Scrap is greater than remaining batch qty elif total_weight_tmp > round((item.batch_qty - item.consumed_qty), 2) and item.status == "Transferred": mf.append( "items", { "s_warehouse": pwo.wip_warehouse, "item_code": item.item_code, "qty": round((item.batch_qty - item.consumed_qty), 2), "batch_no": item.batch_no }) total_weight_tmp = total_weight_tmp - round( (item.batch_qty - item.consumed_qty), 2) wip_strip = get_bin(item.item_code, pwo.wip_warehouse) new_wip_strip_reserved_qty_for_production = wip_strip.reserved_qty_for_production - ( round((item.batch_qty - item.consumed_qty), 2)) #frappe.msgprint("total scrap weight {0}".format(total_weight_tmp)) temp_val = (round((item.batch_qty - item.consumed_qty), 2)) item.db_set("consumed_qty", item.batch_qty) update_projected_qty( item.item_code, pwo.wip_warehouse, None, None, new_wip_strip_reserved_qty_for_production) mf.save() temp_basic_rate = round(mf.total_outgoing_value / total_weight, 2) if pipe_jala_bora_temp != 0: mf.append( "items", { "t_warehouse": pwo.scrap_warehouse, "item_code": "Pipe Jala Bora", "qty": pipe_jala_bora_temp, "basic_rate": temp_basic_rate }) pipe_jala_bora_temp += pwo.pipe_jala_bora pwo.db_set("pipe_jala_bora", pipe_jala_bora_temp) if phakra_pipe_temp != 0: mf.append( "items", { "t_warehouse": pwo.scrap_warehouse, "item_code": "Phakra Pipe", "qty": phakra_pipe_temp, "basic_rate": temp_basic_rate }) phakra_pipe_temp += pwo.phakra_pipe pwo.db_set("phakra_pipe", phakra_pipe_temp) if bari_end_cut_temp != 0: mf.append( "items", { "t_warehouse": pwo.scrap_warehouse, "item_code": "Bari End Cut", "qty": bari_end_cut_temp, "basic_rate": temp_basic_rate }) bari_end_cut_temp += pwo.bari_end_cut pwo.db_set("bari_end_cut", bari_end_cut_temp) mf.save() mf.submit() set_pwo_status(pipes_work_order, "Quality Inspection")
def get_item_stock_of_default(item, warehouse): qty = 0 bin = get_bin(item, warehouse) qty = bin.actual_qty return qty
def update_item_stock(item_code, woocommerce_settings, bin=None): item = frappe.get_doc("Item", item_code) if item.sync_qty_with_woocommerce: if not item.woocommerce_product_id: make_woocommerce_log( title="WooCommerce ID missing", status="Error", method="sync_woocommerce_items", message= "Please sync WooCommerce IDs to ERP (missing for item {0})". format(item_code), request_data=item_code, exception=True) else: # removed bin date check # check bin creation date last_sync_datetime = get_datetime( woocommerce_settings.last_sync_datetime) bin_since_last_sync = frappe.db.sql( """SELECT COUNT(`name`) FROM `tabBin` WHERE `item_code` = '{item_code}' AND `modified` > '{last_sync_datetime}'""" .format(item_code=item_code, last_sync_datetime=last_sync_datetime), as_list=True)[0][0] if bin_since_last_sync > 0: bin = get_bin(item_code, woocommerce_settings.warehouse) qty = bin.actual_qty for warehouse in woocommerce_settings.warehouses: _bin = get_bin(item_code, warehouse.warehouse) qty += _bin.actual_qty # bugfix #1582: variant control from WooCommerce, not ERPNext #if item.woocommerce_variant_id and int(item.woocommerce_variant_id) > 0: #item_data, resource = get_product_update_dict_and_resource(item.woocommerce_product_id, item.woocommerce_variant_id, is_variant=True, actual_qty=qty) #else: #item_data, resource = get_product_update_dict_and_resource(item.woocommerce_product_id, item.woocommerce_variant_id, actual_qty=qty) if item.woocommerce_product_id and item.variant_of: # item = variant template_item = frappe.get_doc( "Item", item.variant_of).woocommerce_product_id item_data, resource = get_product_update_dict_and_resource( template_item, woocommerce_variant_id=item.woocommerce_product_id, is_variant=True, actual_qty=qty) else: # item = single item_data, resource = get_product_update_dict_and_resource( item.woocommerce_product_id, actual_qty=qty) try: #make_woocommerce_log(title="Update stock of {0}".format(item.barcode), status="Started", method="update_item_stock", message="Resource: {0}, data: {1}".format(resource, item_data)) put_request(resource, item_data) except requests.exceptions.HTTPError as e: if e.args[0] and e.args[0].startswith("404"): make_woocommerce_log(title=e.message, status="Error", method="update_item_stock", message=frappe.get_traceback(), request_data=item_data, exception=True) disable_woocommerce_sync_for_item(item) else: raise e
def update_reserved_qty_for_production(self, items=None): '''update reserved_qty_for_production in bins''' for d in self.required_items: if d.source_warehouse: stock_bin = get_bin(d.item_code, d.source_warehouse) stock_bin.update_reserved_qty_for_production()
def update_reserved_qty_for_subcontract(self): for d in self.supplied_items: if d.rm_item_code: stock_bin = get_bin(d.rm_item_code, d.reserve_warehouse) stock_bin.update_reserved_qty_for_sub_contracting()
def pwo_update_bin(self): if self.docstatus == 1: #Updating Pipe Item Bin if round(self.qty, 2) != 0 and self.t_warehouse: init_bin(self.production_item, self.t_warehouse) pipe_bin = get_bin(self.production_item, self.t_warehouse) new_indented_qty = 0 new_indented_qty = pipe_bin.indented_qty - self.req_qty new_planned_qty = 0 new_planned_qty = pipe_bin.planned_qty + round(self.qty, 2) #Updating projected quantity update_projected_qty(self.production_item, self.t_warehouse, new_indented_qty, new_planned_qty, None) #Updating Strip Item(s) Bin if self.required_items: #Looping through required items for d in self.required_items: new_strip_reserved_qty_for_production = 0 #Variable for new reserved qty new_strip_indented_qty = 0 wip_reserved_qty = 0 #Variable for new indented qty init_bin(d.item_code, d.batch_warehouse ) #Checking if any value is "None" in bin strip_bin_store = get_bin( d.item_code, d.batch_warehouse ) #Declaring bin object for source warehouse init_bin(d.item_code, self.wip_warehouse ) #Checking if any value is "None" in bin strip_bin_wip = get_bin( d.item_code, self.wip_warehouse ) #Declaring bin object for wip warehouse if d.batch_qty != 0: #For Source Warehouse new_strip_reserved_qty_for_production += strip_bin_store.reserved_qty_for_production + d.batch_qty #For WIP Warehouse if self.skip_transfer == 0: new_strip_indented_qty += strip_bin_wip.indented_qty + d.batch_qty wip_reserved_qty += strip_bin_wip.reserved_qty_for_production + d.batch_qty #Updating projected quantity update_projected_qty( d.item_code, d.batch_warehouse, None, None, new_strip_reserved_qty_for_production) update_projected_qty(d.item_code, self.wip_warehouse, new_strip_indented_qty, strip_bin_wip.planned_qty, wip_reserved_qty) else: #Updating Pipe Item Bin on Cancel if round(self.qty, 2) != 0 and self.t_warehouse: pipe_bin = get_bin(self.production_item, self.t_warehouse) new_indented_qty = 0 new_indented_qty = pipe_bin.indented_qty + self.req_qty new_planned_qty = 0 new_planned_qty = pipe_bin.planned_qty - round(self.qty, 2) #Updating projected quantity update_projected_qty(self.production_item, self.t_warehouse, new_indented_qty, new_planned_qty, None) #Updating Strip Item(s) Bin if self.required_items: for d in self.required_items: new_strip_reserved_qty_for_production = 0 #Variable for new reserved qty new_strip_indented_qty = 0 #Variable for new indented qty strip_bin_store = get_bin( d.item_code, d.batch_warehouse ) #Declaring bin object for source warehouse strip_bin_wip = get_bin( d.item_code, self.wip_warehouse ) #Declaring bin object for wip warehouse if d.batch_qty != 0: new_strip_reserved_qty_for_production += strip_bin_store.reserved_qty_for_production - d.batch_qty #For WIP Warehouse if self.skip_transfer == 0: new_strip_indented_qty += strip_bin_wip.indented_qty - d.batch_qty #Updating projected quantity update_projected_qty( d.item_code, d.batch_warehouse, None, None, new_strip_reserved_qty_for_production) update_projected_qty(d.item_code, self.wip_warehouse, new_strip_indented_qty, None, None)
def test_bin(item_code, warehouse): bin = get_bin(item_code, warehouse) print("{0} has {1} of {2}".format(warehouse, bin.actual_qty, item_code)) return
def update_item_stock(item_code, woocommerce_settings, bin=None): item = frappe.get_doc("Item", item_code) items = frappe.db.sql(""" select sum(soi.qty ) as qty from `tabSales Order` as so inner join `tabSales Order Item` as soi on soi.parent = so.name where so.status in ("To Deliver and Bill","To Deliver") and soi.item_code = %s group by soi.item_code """, (item_code), as_list=1) if items and items[0] and items[0][0]: dec_qty = items[0][0] else: dec_qty = 0 if item.sync_qty_with_woocommerce_sync: if not bin: bin = get_bin(item_code, woocommerce_settings.warehouse) warehouses = frappe.db.get_values( "woocommerce Warehouse", {"parent": "Woocommerce Sync Settings"}, "warehouse") qty = bin.actual_qty bin_warehouse_is_sync = False for warehouse_in_list in warehouses: # bin = get_bin(item.get("item_code"), warehouse_in_list) temp_qty = 0 if bin.warehouse == warehouse_in_list[0]: bin_warehouse_is_sync = True continue temp_qty = frappe.db.get_value("Bin", { "item_code": item_code, "warehouse": warehouse_in_list[0] }, "actual_qty") if temp_qty: qty += temp_qty if not (bin_warehouse_is_sync or bin.warehouse == woocommerce_settings.warehouse): return qty -= dec_qty if not item.woocommerce_sync_product_id and not item.variant_of: sync_item_with_woocommerce(item, woocommerce_settings.price_list, woocommerce_settings.warehouse) if item.sync_with_woocommerce_sync and item.woocommerce_sync_product_id: if item.variant_of: item_data, resource = get_product_update_dict_and_resource( frappe.get_value("Item", item.variant_of, "woocommerce_sync_product_id"), item.woocommerce_sync_variant_id, is_variant=True, actual_qty=qty) else: item_data, resource = get_product_update_dict_and_resource( item.woocommerce_sync_product_id, item.woocommerce_sync_variant_id, actual_qty=qty) try: put_request(resource, item_data) except requests.exceptions.HTTPError as e: if e.args[0] and e.args[0].startswith("404"): make_woocommerce_log(title=e.message, status="Error", method="sync_woocommerce_items", message=frappe.get_traceback(), request_data=item_data, exception=True) disable_woocommerce_sync_for_item(item) else: raise e
def add_to_bin(): get_bin("MLA636633322", "Productos terminados - I")
def batch_qty(batch_no, s_warehouse, required_item): s_batch_qty = get_batch_qty(batch_no, s_warehouse) coil_bin = get_bin(required_item, s_warehouse) s_reserved_qty = coil_bin.reserved_qty_for_production available_batch_qty = s_batch_qty - s_reserved_qty return available_batch_qty