def test_reserved_qty_for_over_delivery_with_packing_list(self):
		make_stock_entry(target="_Test Warehouse - _TC", qty=10, rate=100)
		make_stock_entry(item="_Test Item Home Desktop 100", target="_Test Warehouse - _TC", qty=10, rate=100)
		
		# set over-delivery tolerance
		frappe.db.set_value('Item', "_Test Product Bundle Item", 'tolerance', 50)

		existing_reserved_qty_item1 = get_reserved_qty("_Test Item")
		existing_reserved_qty_item2 = get_reserved_qty("_Test Item Home Desktop 100")

		so = make_sales_order(item_code="_Test Product Bundle Item")

		self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 50)
		self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"),
			existing_reserved_qty_item2 + 20)

		dn = create_dn_against_so(so.name, 15)

		total_projected_qty = get_total_projected_qty('_Test Item')
		item_doc = frappe.get_doc('Item', '_Test Item')
		self.assertEqual(total_projected_qty,  item_doc.total_projected_qty)

		self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1)
		self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"),
			existing_reserved_qty_item2)

		dn.cancel()
		self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 50)
		self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"),
			existing_reserved_qty_item2 + 20)
Beispiel #2
0
	def test_warehouse_merging(self):
		set_perpetual_inventory(1)

		create_warehouse("Test Warehouse for Merging 1")
		create_warehouse("Test Warehouse for Merging 2")

		make_stock_entry(item_code="_Test Item", target="Test Warehouse for Merging 1 - _TC",
			qty=1, rate=100)
		make_stock_entry(item_code="_Test Item", target="Test Warehouse for Merging 2 - _TC",
			qty=1, rate=100)

		existing_bin_qty = (
			cint(frappe.db.get_value("Bin",
				{"item_code": "_Test Item", "warehouse": "Test Warehouse for Merging 1 - _TC"}, "actual_qty"))
			+ cint(frappe.db.get_value("Bin",
				{"item_code": "_Test Item", "warehouse": "Test Warehouse for Merging 2 - _TC"}, "actual_qty"))
		)

		rename_doc("Warehouse", "Test Warehouse for Merging 1 - _TC",
			"Test Warehouse for Merging 2 - _TC", merge=True)

		self.assertFalse(frappe.db.exists("Warehouse", "Test Warehouse for Merging 1 - _TC"))

		bin_qty = frappe.db.get_value("Bin",
			{"item_code": "_Test Item", "warehouse": "Test Warehouse for Merging 2 - _TC"}, "actual_qty")

		self.assertEqual(bin_qty, existing_bin_qty)

		self.assertTrue(frappe.db.get_value("Warehouse",
			filters={"account": "Test Warehouse for Merging 2 - _TC"}))
	def test_material_issue_gl_entry(self):
		set_perpetual_inventory()

		make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC",
			qty=50, basic_rate=100, expense_account="Stock Adjustment - _TC")

		mi = make_stock_entry(item_code="_Test Item", source="_Test Warehouse - _TC", 
			qty=40, expense_account="Stock Adjustment - _TC")

		self.check_stock_ledger_entries("Stock Entry", mi.name,
			[["_Test Item", "_Test Warehouse - _TC", -40.0]])

		stock_in_hand_account = frappe.db.get_value("Account", {"account_type": "Warehouse",
			"warehouse": "_Test Warehouse - _TC"})

		stock_value_diff = abs(frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Stock Entry",
			"voucher_no": mi.name}, "stock_value_difference"))

		self.check_gl_entries("Stock Entry", mi.name,
			sorted([
				[stock_in_hand_account, 0.0, stock_value_diff],
				["Stock Adjustment - _TC", stock_value_diff, 0.0]
			])
		)

		mi.cancel()

		self.assertFalse(frappe.db.sql("""select name from `tabStock Ledger Entry`
			where voucher_type='Stock Entry' and voucher_no=%s""", mi.name))

		self.assertFalse(frappe.db.sql("""select name from `tabGL Entry`
			where voucher_type='Stock Entry' and voucher_no=%s""", mi.name))
	def test_reserved_qty_for_partial_delivery(self):
		make_stock_entry(target="_Test Warehouse - _TC", qty=10, rate=100)
		existing_reserved_qty = get_reserved_qty()

		so = make_sales_order()
		self.assertEqual(get_reserved_qty(), existing_reserved_qty + 10)

		dn = create_dn_against_so(so.name)
		self.assertEqual(get_reserved_qty(), existing_reserved_qty + 5)

		# close so
		so.load_from_db()
		so.update_status("Closed")
		self.assertEqual(get_reserved_qty(), existing_reserved_qty)

		# unclose so
		so.load_from_db()
		so.update_status('Draft')
		self.assertEqual(get_reserved_qty(), existing_reserved_qty + 5)

		dn.cancel()
		self.assertEqual(get_reserved_qty(), existing_reserved_qty + 10)

		# cancel
		so.load_from_db()
		so.cancel()
		self.assertEqual(get_reserved_qty(), existing_reserved_qty)
Beispiel #5
0
	def test_reserved_qty_for_over_delivery_via_sales_invoice(self):
		make_stock_entry(target="_Test Warehouse - _TC", qty=10, rate=100)

		# set over-delivery tolerance
		frappe.db.set_value('Item', "_Test Item", 'tolerance', 50)

		existing_reserved_qty = get_reserved_qty()

		so = make_sales_order()
		self.assertEqual(get_reserved_qty(), existing_reserved_qty + 10)

		si = make_sales_invoice(so.name)
		si.update_stock = 1
		si.get("items")[0].qty = 12
		si.insert()
		si.submit()

		self.assertEqual(get_reserved_qty(), existing_reserved_qty)

		so.load_from_db()
		self.assertEqual(so.get("items")[0].delivered_qty, 12)
		self.assertEqual(so.per_delivered, 100)

		si.cancel()
		self.assertEqual(get_reserved_qty(), existing_reserved_qty + 10)

		so.load_from_db()
		self.assertEqual(so.get("items")[0].delivered_qty, 0)
		self.assertEqual(so.per_delivered, 0)
	def test_production_order(self):
		from erpnext.manufacturing.doctype.production_order.production_order \
			import make_stock_entry as _make_stock_entry
		bom_no, bom_operation_cost = frappe.db.get_value("BOM", {"item": "_Test FG Item 2",
			"is_default": 1, "docstatus": 1}, ["name", "operating_cost"])

		production_order = frappe.new_doc("Production Order")
		production_order.update({
			"company": "_Test Company",
			"fg_warehouse": "_Test Warehouse 1 - _TC",
			"production_item": "_Test FG Item 2",
			"bom_no": bom_no,
			"qty": 1.0,
			"stock_uom": "_Test UOM",
			"wip_warehouse": "_Test Warehouse - _TC",
			"additional_operating_cost": 1000
		})
		production_order.insert()
		production_order.submit()

		make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, basic_rate=100)

		stock_entry = _make_stock_entry(production_order.name, "Manufacture", 1)

		rm_cost = 0
		for d in stock_entry.get("items"):
			if d.s_warehouse:
				rm_cost += flt(d.amount)

		fg_cost = filter(lambda x: x.item_code=="_Test FG Item 2", stock_entry.get("items"))[0].amount
		self.assertEqual(fg_cost,
			flt(rm_cost + bom_operation_cost + production_order.additional_operating_cost, 2))
Beispiel #7
0
	def test_reserved_qty_for_over_delivery(self):
		make_stock_entry(target="_Test Warehouse - _TC", qty=10, rate=100)
		# set over-delivery tolerance
		frappe.db.set_value('Item', "_Test Item", 'tolerance', 50)

		existing_reserved_qty = get_reserved_qty()

		so = make_sales_order()
		self.assertEqual(get_reserved_qty(), existing_reserved_qty + 10)

		dn = create_dn_against_so(so.name, 15)
		self.assertEqual(get_reserved_qty(), existing_reserved_qty)

		dn.cancel()
		self.assertEqual(get_reserved_qty(), existing_reserved_qty + 10)
	def test_reserved_qty_for_partial_delivery_with_packing_list(self):
		make_stock_entry(target="_Test Warehouse - _TC", qty=10, rate=100)
		make_stock_entry(item="_Test Item Home Desktop 100", target="_Test Warehouse - _TC", qty=10, rate=100)
		
		
		existing_reserved_qty_item1 = get_reserved_qty("_Test Item")
		existing_reserved_qty_item2 = get_reserved_qty("_Test Item Home Desktop 100")

		so = make_sales_order(item_code="_Test Product Bundle Item")

		self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 50)
		self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"),
			existing_reserved_qty_item2 + 20)

		dn = create_dn_against_so(so.name)

		self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 25)
		self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"),
			existing_reserved_qty_item2 + 10)

		# close so
		so.load_from_db()
		so.update_status("Closed")

		self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1)
		self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2)

		total_projected_qty = get_total_projected_qty('_Test Item')
		item_doc = frappe.get_doc('Item', '_Test Item')
		self.assertEqual(total_projected_qty,  item_doc.total_projected_qty)

		# unclose so
		so.load_from_db()
		so.update_status('Draft')

		self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 25)
		self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"),
			existing_reserved_qty_item2 + 10)

		dn.cancel()
		self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 50)
		self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"),
			existing_reserved_qty_item2 + 20)

		so.load_from_db()
		so.cancel()
		self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1)
		self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2)
    def test_hash_naming(self):
        # disable naming series
        for doctype in ("GL Entry", "Stock Ledger Entry"):
            make_property_setter(
                doctype=doctype,
                for_doctype=True,
                property="autoname",
                value="hash",
                property_type="Data",
                fieldname=None,
            )

        se = make_stock_entry(item_code=self.item,
                              to_warehouse=self.warehouse,
                              qty=10,
                              rate=100,
                              company=self.company)

        gle, sle = self.get_gle_sles(se)
        rename_gle_sle_docs()
        renamed_gle, renamed_sle = self.get_gle_sles(se)

        self.assertEqual(gle,
                         renamed_gle,
                         msg="GLEs are renamed while using hash naming")
        self.assertEqual(sle,
                         renamed_sle,
                         msg="SLEs are renamed while using hash naming")
        se.cancel()
	def test_serial_no_cancellation(self):
		from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry

		item = create_item("Stock-Reco-Serial-Item-9", is_stock_item=1)
		if not item.has_serial_no:
			item.has_serial_no = 1
			item.serial_no_series = "SRS9.####"
			item.save()

		item_code = item.name
		warehouse = "_Test Warehouse - _TC"

		se1 = make_stock_entry(item_code=item_code, target=warehouse, qty=10, basic_rate=700)

		serial_nos = get_serial_nos(se1.items[0].serial_no)
		# reduce 1 item
		serial_nos.pop()
		new_serial_nos = "\n".join(serial_nos)

		sr = create_stock_reconciliation(
			item_code=item.name, warehouse=warehouse, serial_no=new_serial_nos, qty=9
		)
		sr.cancel()

		active_sr_no = frappe.get_all(
			"Serial No", filters={"item_code": item_code, "warehouse": warehouse, "status": "Active"}
		)

		self.assertEqual(len(active_sr_no), 10)
Beispiel #11
0
	def test_gle_for_opening_stock_entry(self):
		mr = make_stock_entry(
			item_code="_Test Item",
			target="Stores - TCP1",
			company="_Test Company with perpetual inventory",
			qty=50,
			basic_rate=100,
			expense_account="Stock Adjustment - TCP1",
			is_opening="Yes",
			do_not_save=True,
		)

		self.assertRaises(OpeningEntryAccountError, mr.save)

		mr.items[0].expense_account = "Temporary Opening - TCP1"

		mr.save()
		mr.submit()

		is_opening = frappe.db.get_value(
			"GL Entry",
			filters={"voucher_type": "Stock Entry", "voucher_no": mr.name},
			fieldname="is_opening",
		)
		self.assertEqual(is_opening, "Yes")
Beispiel #12
0
    def test_raise_extra_transfer_materials(self):
        from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
        warehouse = "_Test Warehouse FG 1 - _TC"

        if not frappe.db.exists('Warehouse', warehouse):
            create_warehouse("_Test Warehouse FG 1")

        outward_entry = make_stock_entry(item_code="_Test Item",
                                         purpose="Send to Warehouse",
                                         source="_Test Warehouse - _TC",
                                         target="_Test Warehouse 1 - _TC",
                                         qty=50,
                                         basic_rate=100)

        inward_entry1 = make_stock_in_entry(outward_entry.name)
        inward_entry1.items[0].t_warehouse = warehouse
        inward_entry1.items[0].qty = 25
        inward_entry1.submit()

        inward_entry2 = make_stock_in_entry(outward_entry.name)
        inward_entry2.items[0].t_warehouse = warehouse
        inward_entry2.items[0].qty = 35

        self.assertRaises(ExtraMaterialReceived, inward_entry2.submit)
        print(inward_entry2.name)
	def test_material_transfer_gl_entry(self):
		set_perpetual_inventory()

		create_stock_reconciliation(qty=100, rate=100)

		mtn = make_stock_entry(item_code="_Test Item", source="_Test Warehouse - _TC",
			target="_Test Warehouse 1 - _TC", qty=45)

		self.check_stock_ledger_entries("Stock Entry", mtn.name,
			[["_Test Item", "_Test Warehouse - _TC", -45.0], ["_Test Item", "_Test Warehouse 1 - _TC", 45.0]])

		stock_in_hand_account = frappe.db.get_value("Account", {"account_type": "Warehouse",
			"warehouse": mtn.get("items")[0].s_warehouse})

		fixed_asset_account = frappe.db.get_value("Account", {"account_type": "Warehouse",
			"warehouse": mtn.get("items")[0].t_warehouse})

		stock_value_diff = abs(frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Stock Entry",
			"voucher_no": mtn.name, "warehouse": "_Test Warehouse - _TC"}, "stock_value_difference"))

		self.check_gl_entries("Stock Entry", mtn.name,
			sorted([
				[stock_in_hand_account, 0.0, stock_value_diff],
				[fixed_asset_account, stock_value_diff, 0.0],
			])
		)

		mtn.cancel()
		self.assertFalse(frappe.db.sql("""select * from `tabStock Ledger Entry`
			where voucher_type='Stock Entry' and voucher_no=%s""", mtn.name))

		self.assertFalse(frappe.db.sql("""select * from `tabGL Entry`
			where voucher_type='Stock Entry' and voucher_no=%s""", mtn.name))
	def test_material_receipt_gl_entry(self):
		set_perpetual_inventory()

		mr = make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC",
			qty=50, basic_rate=100, expense_account="Stock Adjustment - _TC")
					
		stock_in_hand_account = frappe.db.get_value("Account", {"account_type": "Warehouse",
			"warehouse": mr.get("items")[0].t_warehouse})

		self.check_stock_ledger_entries("Stock Entry", mr.name,
			[["_Test Item", "_Test Warehouse - _TC", 50.0]])

		self.check_gl_entries("Stock Entry", mr.name,
			sorted([
				[stock_in_hand_account, 5000.0, 0.0],
				["Stock Adjustment - _TC", 0.0, 5000.0]
			])
		)

		mr.cancel()

		self.assertFalse(frappe.db.sql("""select * from `tabStock Ledger Entry`
			where voucher_type='Stock Entry' and voucher_no=%s""", mr.name))

		self.assertFalse(frappe.db.sql("""select * from `tabGL Entry`
			where voucher_type='Stock Entry' and voucher_no=%s""", mr.name))
Beispiel #15
0
    def set_opening_stock(self):
        '''set opening stock'''
        if not self.is_stock_item or self.has_serial_no or self.has_batch_no:
            return

        if not self.valuation_rate and self.standard_rate:
            self.valuation_rate = self.standard_rate

        if not self.valuation_rate:
            frappe.throw(
                _("Valuation Rate is mandatory if Opening Stock entered"))

        from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry

        # default warehouse, or Stores
        default_warehouse = (self.default_warehouse
                             or frappe.db.get_single_value(
                                 'Stock Settings', 'default_warehouse')
                             or frappe.db.get_value(
                                 'Warehouse', {'warehouse_name': _('Stores')}))

        if default_warehouse:
            stock_entry = make_stock_entry(item_code=self.name,
                                           target=default_warehouse,
                                           qty=self.opening_stock,
                                           rate=self.valuation_rate)

            stock_entry.add_comment("Comment", _("Opening Stock"))
Beispiel #16
0
    def test_reserved_qty_for_over_delivery(self):
        make_stock_entry(target="_Test Warehouse - _TC", qty=10, rate=100)
        # set over-delivery allowance
        frappe.db.set_value('Item', "_Test Item",
                            'over_delivery_receipt_allowance', 50)

        existing_reserved_qty = get_reserved_qty()

        so = make_sales_order()
        self.assertEqual(get_reserved_qty(), existing_reserved_qty + 10)

        dn = create_dn_against_so(so.name, 15)
        self.assertEqual(get_reserved_qty(), existing_reserved_qty)

        dn.cancel()
        self.assertEqual(get_reserved_qty(), existing_reserved_qty + 10)
Beispiel #17
0
	def set_opening_stock(self):
		'''set opening stock'''
		if not self.is_stock_item or self.has_serial_no or self.has_batch_no:
			return

		if not self.valuation_rate and self.standard_rate:
			self.valuation_rate = self.standard_rate

		if not self.valuation_rate:
			frappe.throw(_("Valuation Rate is mandatory if Opening Stock entered"))

		from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry

		# default warehouse, or Stores
		for default in self.item_defaults or [frappe._dict({'company': frappe.defaults.get_defaults().company})]:
			default_warehouse = (default.default_warehouse
					or frappe.db.get_single_value('Stock Settings', 'default_warehouse'))
			if default_warehouse:
				warehouse_company = frappe.db.get_value("Warehouse", default_warehouse, "company")

			if not default_warehouse or warehouse_company != default.company:
				default_warehouse = frappe.db.get_value('Warehouse',
					{'warehouse_name': _('Stores'), 'company': default.company})

			if default_warehouse:
				stock_entry = make_stock_entry(item_code=self.name, target=default_warehouse, qty=self.opening_stock,
					rate=self.valuation_rate, company=default.company)

				stock_entry.add_comment("Comment", _("Opening Stock"))
    def test_variant_work_order(self):
        bom_no = frappe.db.get_value("BOM", {
            "item": "_Test Variant Item",
            "is_default": 1,
            "docstatus": 1
        })

        work_order = frappe.new_doc("Work Order")
        work_order.update({
            "company": "_Test Company",
            "fg_warehouse": "_Test Warehouse 1 - _TC",
            "production_item": "_Test Variant Item-S",
            "bom_no": bom_no,
            "qty": 1.0,
            "stock_uom": "_Test UOM",
            "wip_warehouse": "_Test Warehouse - _TC",
            "skip_transfer": 1
        })
        work_order.insert()
        work_order.submit()

        from erpnext.manufacturing.doctype.work_order.work_order import make_stock_entry

        stock_entry = frappe.get_doc(
            make_stock_entry(work_order.name, "Manufacture", 1))
        stock_entry.insert()
        self.assertTrue(
            "_Test Variant Item-S" in [d.item_code for d in stock_entry.items])
    def test_same_serial_nos_in_repack_or_manufacture_entries(self):
        s1 = make_serialized_item(target_warehouse="_Test Warehouse - _TC")
        serial_nos = s1.get("items")[0].serial_no

        s2 = make_stock_entry(item_code="_Test Serialized Item With Series",
                              source="_Test Warehouse - _TC",
                              qty=2,
                              basic_rate=100,
                              purpose="Repack",
                              serial_no=serial_nos,
                              do_not_save=True)

        s2.append(
            "items", {
                "item_code": "_Test Serialized Item",
                "t_warehouse": "_Test Warehouse - _TC",
                "qty": 2,
                "basic_rate": 120,
                "expense_account": "Stock Adjustment - _TC",
                "conversion_factor": 1.0,
                "cost_center": "_Test Cost Center - _TC",
                "serial_no": serial_nos
            })

        s2.submit()
        s2.cancel()
Beispiel #20
0
    def test_goods_in_transit(self):
        from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
        warehouse = "_Test Warehouse FG 1 - _TC"

        if not frappe.db.exists('Warehouse', warehouse):
            create_warehouse("_Test Warehouse FG 1")

        outward_entry = make_stock_entry(item_code="_Test Item",
                                         purpose="Send to Warehouse",
                                         source="_Test Warehouse - _TC",
                                         target="_Test Warehouse 1 - _TC",
                                         qty=50,
                                         basic_rate=100)

        inward_entry1 = make_stock_in_entry(outward_entry.name)
        inward_entry1.items[0].t_warehouse = warehouse
        inward_entry1.items[0].qty = 25
        inward_entry1.submit()

        doc = frappe.get_doc('Stock Entry', outward_entry.name)
        self.assertEqual(doc.per_transferred, 50)

        inward_entry2 = make_stock_in_entry(outward_entry.name)
        inward_entry2.items[0].t_warehouse = warehouse
        inward_entry2.items[0].qty = 25
        inward_entry2.submit()

        doc = frappe.get_doc('Stock Entry', outward_entry.name)
        self.assertEqual(doc.per_transferred, 100)
    def test_material_receipt_gl_entry(self):
        company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC',
                                      'company')
        set_perpetual_inventory(1, company)

        mr = make_stock_entry(item_code="_Test Item",
                              target="_Test Warehouse - _TC",
                              qty=50,
                              basic_rate=100,
                              expense_account="Stock Adjustment - _TC")

        stock_in_hand_account = get_inventory_account(
            mr.company,
            mr.get("items")[0].t_warehouse)
        self.check_stock_ledger_entries(
            "Stock Entry", mr.name,
            [["_Test Item", "_Test Warehouse - _TC", 50.0]])

        self.check_gl_entries(
            "Stock Entry", mr.name,
            sorted([[stock_in_hand_account, 5000.0, 0.0],
                    ["Stock Adjustment - _TC", 0.0, 5000.0]]))

        mr.cancel()

        self.assertFalse(
            frappe.db.sql(
                """select * from `tabStock Ledger Entry`
			where voucher_type='Stock Entry' and voucher_no=%s""", mr.name))

        self.assertFalse(
            frappe.db.sql(
                """select * from `tabGL Entry`
			where voucher_type='Stock Entry' and voucher_no=%s""", mr.name))
Beispiel #22
0
	def test_reserved_qty_for_partial_delivery_with_packing_list(self):
		make_stock_entry(target="_Test Warehouse - _TC", qty=10, rate=100)
		make_stock_entry(item="_Test Item Home Desktop 100", target="_Test Warehouse - _TC", qty=10, rate=100)

		existing_reserved_qty_item1 = get_reserved_qty("_Test Item")
		existing_reserved_qty_item2 = get_reserved_qty("_Test Item Home Desktop 100")

		so = make_sales_order(item_code="_Test Product Bundle Item")

		self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 50)
		self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"),
			existing_reserved_qty_item2 + 20)

		dn = create_dn_against_so(so.name)

		self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 25)
		self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"),
			existing_reserved_qty_item2 + 10)

		# close so
		so.load_from_db()
		so.update_status("Closed")

		self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1)
		self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2)

		total_projected_qty = get_total_projected_qty('_Test Item')
		item_doc = frappe.get_doc('Item', '_Test Item')
		self.assertEqual(total_projected_qty,  item_doc.total_projected_qty)

		# unclose so
		so.load_from_db()
		so.update_status('Draft')

		self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 25)
		self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"),
			existing_reserved_qty_item2 + 10)

		dn.cancel()
		self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 50)
		self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"),
			existing_reserved_qty_item2 + 20)

		so.load_from_db()
		so.cancel()
		self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1)
		self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2)
Beispiel #23
0
    def test_work_order(self):
        from erpnext.manufacturing.doctype.work_order.work_order \
         import make_stock_entry as _make_stock_entry
        bom_no, bom_operation_cost = frappe.db.get_value(
            "BOM", {
                "item": "_Test FG Item 2",
                "is_default": 1,
                "docstatus": 1
            }, ["name", "operating_cost"])

        work_order = frappe.new_doc("Work Order")
        work_order.update({
            "company": "_Test Company",
            "fg_warehouse": "_Test Warehouse 1 - _TC",
            "production_item": "_Test FG Item 2",
            "bom_no": bom_no,
            "qty": 1.0,
            "stock_uom": "_Test UOM",
            "wip_warehouse": "_Test Warehouse - _TC",
            "additional_operating_cost": 1000
        })
        work_order.insert()
        work_order.submit()

        make_stock_entry(item_code="_Test Item",
                         target="_Test Warehouse - _TC",
                         qty=50,
                         basic_rate=100)
        make_stock_entry(item_code="_Test Item 2",
                         target="_Test Warehouse - _TC",
                         qty=50,
                         basic_rate=20)

        stock_entry = _make_stock_entry(work_order.name, "Manufacture", 1)

        rm_cost = 0
        for d in stock_entry.get("items"):
            if d.item_code != "_Test FG Item 2":
                rm_cost += flt(d.amount)
        fg_cost = list(
            filter(lambda x: x.item_code == "_Test FG Item 2",
                   stock_entry.get("items")))[0].amount
        self.assertEqual(
            fg_cost,
            flt(
                rm_cost + bom_operation_cost +
                work_order.additional_operating_cost, 2))
Beispiel #24
0
    def test_back_dated_entry_not_allowed(self):
        # Back dated stock transactions are only allowed to stock managers
        frappe.db.set_value(
            "Stock Settings", None,
            "role_allowed_to_create_edit_back_dated_transactions",
            "Stock Manager")

        # Set User with Stock User role but not Stock Manager
        try:
            user = frappe.get_doc("User", "*****@*****.**")
            frappe.set_user(user.name)
            user.add_roles("Stock User")
            user.remove_roles("Stock Manager")

            stock_entry_on_today = make_stock_entry(
                target="_Test Warehouse - _TC", qty=10, basic_rate=100)
            back_dated_se_1 = make_stock_entry(target="_Test Warehouse - _TC",
                                               qty=10,
                                               basic_rate=100,
                                               posting_date=add_days(
                                                   today(), -1),
                                               do_not_submit=True)

            # Block back-dated entry
            self.assertRaises(BackDatedStockTransaction,
                              back_dated_se_1.submit)

            frappe.set_user("Administrator")
            user.add_roles("Stock Manager")
            frappe.set_user(user.name)

            # Back dated entry allowed to Stock Manager
            back_dated_se_2 = make_stock_entry(target="_Test Warehouse - _TC",
                                               qty=10,
                                               basic_rate=100,
                                               posting_date=add_days(
                                                   today(), -1))

            back_dated_se_2.cancel()
            stock_entry_on_today.cancel()

        finally:
            frappe.db.set_value(
                "Stock Settings", None,
                "role_allowed_to_create_edit_back_dated_transactions", None)
            frappe.set_user("Administrator")
            user.remove_roles("Stock Manager")
def on_submit(doc, method):
	"""Handle sample item"""
	if frappe.flags.in_import or frappe.flags.in_test:
		return

	if not doc.is_sample:
		return

	valid_groups = [
		_('Flower Lot'),
		_('CO2 Hash Oil'),
		_('Food Grade Solvent Extract'),
		_('Hydrocarbon Wax'),
		_('Marijuana Extract for Inhalation'),
		_('Solid Marijuana Infused Edible'),
		_('Usable Marijuana')
	]

	item_group = frappe.get_value("Item", doc.item_code, "item_group")
	if not _(item_group) in valid_groups:
		frappe.throw(
			_("Item is not eligible for making sample."),
			title="Invalid Item")

	# Stock update had been handled by delivery_note
	if doc.inspection_type == "Outgoing" and doc.delivery_note_no:
		return

	inventories = get_data(item_code=doc.item_code)
	source_warehouse = None
	actual_qty = 0

	for inventory in inventories:
		if inventory.actual_qty > actual_qty:
			actual_qty = inventory.actual_qty

		if inventory.actual_qty >= doc.sample_size:
			source_warehouse = inventory.warehouse
			break

	if not source_warehouse:
		frappe.throw(
			_("Qty is not available for provided sample size. Qty remaining <strong>{0}</strong>.").format(actual_qty),
			title="Insufficient Stock")

	make_stock_entry(item_code=doc.item_code, source=source_warehouse, qty=doc.sample_size)
    def test_material_issue_gl_entry(self):
        set_perpetual_inventory()

        make_stock_entry(item_code="_Test Item",
                         target="_Test Warehouse - _TC",
                         qty=50,
                         basic_rate=100,
                         expense_account="Stock Adjustment - _TC")

        mi = make_stock_entry(item_code="_Test Item",
                              source="_Test Warehouse - _TC",
                              qty=40,
                              expense_account="Stock Adjustment - _TC")

        self.check_stock_ledger_entries(
            "Stock Entry", mi.name,
            [["_Test Item", "_Test Warehouse - _TC", -40.0]])

        stock_in_hand_account = frappe.db.get_value(
            "Account", {
                "account_type": "Stock",
                "warehouse": "_Test Warehouse - _TC"
            })

        stock_value_diff = abs(
            frappe.db.get_value("Stock Ledger Entry", {
                "voucher_type": "Stock Entry",
                "voucher_no": mi.name
            }, "stock_value_difference"))

        self.check_gl_entries(
            "Stock Entry", mi.name,
            sorted([[stock_in_hand_account, 0.0, stock_value_diff],
                    ["Stock Adjustment - _TC", stock_value_diff, 0.0]]))

        mi.cancel()

        self.assertFalse(
            frappe.db.sql(
                """select name from `tabStock Ledger Entry`
			where voucher_type='Stock Entry' and voucher_no=%s""", mi.name))

        self.assertFalse(
            frappe.db.sql(
                """select name from `tabGL Entry`
			where voucher_type='Stock Entry' and voucher_no=%s""", mi.name))
Beispiel #27
0
    def test_picklist_with_multi_uom(self):
        warehouse = "_Test Warehouse - _TC"
        item = make_item(properties={
            "uoms": [dict(uom="Box", conversion_factor=24)]
        }).name
        make_stock_entry(item=item, to_warehouse=warehouse, qty=1000)

        so = make_sales_order(item_code=item, qty=10, rate=42, uom="Box")
        pl = create_pick_list(so.name)
        # pick half the qty
        for loc in pl.locations:
            loc.picked_qty = loc.stock_qty / 2
        pl.save()
        pl.submit()

        so.reload()
        self.assertEqual(so.per_picked, 50)
Beispiel #28
0
	def _make_stock_entry(self, qty, rate=None):
		kwargs = {
			"item_code": self.ITEM_CODE,
			"from_warehouse" if qty < 0 else "to_warehouse": self.WAREHOUSE,
			"rate": rate,
			"qty": abs(qty),
		}
		return make_stock_entry(**kwargs)
    def test_material_transfer_gl_entry(self):
        company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC',
                                      'company')
        set_perpetual_inventory(1, company)

        create_stock_reconciliation(qty=100, rate=100)

        mtn = make_stock_entry(item_code="_Test Item",
                               source="_Test Warehouse - _TC",
                               target="_Test Warehouse 1 - _TC",
                               qty=45)

        self.check_stock_ledger_entries(
            "Stock Entry", mtn.name,
            [["_Test Item", "_Test Warehouse - _TC", -45.0],
             ["_Test Item", "_Test Warehouse 1 - _TC", 45.0]])

        stock_in_hand_account = get_inventory_account(
            mtn.company,
            mtn.get("items")[0].s_warehouse)

        fixed_asset_account = get_inventory_account(
            mtn.company,
            mtn.get("items")[0].t_warehouse)

        if stock_in_hand_account == fixed_asset_account:
            # no gl entry as both source and target warehouse has linked to same account.
            self.assertFalse(
                frappe.db.sql(
                    """select * from `tabGL Entry`
				where voucher_type='Stock Entry' and voucher_no=%s""", mtn.name))

        else:
            stock_value_diff = abs(
                frappe.db.get_value(
                    "Stock Ledger Entry", {
                        "voucher_type": "Stock Entry",
                        "voucher_no": mtn.name,
                        "warehouse": "_Test Warehouse - _TC"
                    }, "stock_value_difference"))

            self.check_gl_entries(
                "Stock Entry", mtn.name,
                sorted([
                    [stock_in_hand_account, 0.0, stock_value_diff],
                    [fixed_asset_account, stock_value_diff, 0.0],
                ]))

        mtn.cancel()
        self.assertFalse(
            frappe.db.sql(
                """select * from `tabStock Ledger Entry`
			where voucher_type='Stock Entry' and voucher_no=%s""", mtn.name))

        self.assertFalse(
            frappe.db.sql(
                """select * from `tabGL Entry`
			where voucher_type='Stock Entry' and voucher_no=%s""", mtn.name))
Beispiel #30
0
    def test_website_item_stock_when_in_stock(self):
        """
		Check if stock details are fetched correctly for available inventory when:
		1) Showing stock availability enabled:
		        - Warehouse set
		        - Warehouse unset
		2) Showing stock availability disabled
		"""
        from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry

        item_code = "Test Mobile Phone"
        create_regular_web_item()
        setup_e_commerce_settings({"show_stock_availability": 1})
        frappe.local.shopping_cart_settings = None

        # set warehouse
        frappe.db.set_value("Website Item", {"item_code": item_code},
                            "website_warehouse", "_Test Warehouse - _TC")

        # stock up item
        stock_entry = make_stock_entry(item_code=item_code,
                                       target="_Test Warehouse - _TC",
                                       qty=2,
                                       rate=100)

        # check if stock details are fetched and item is in stock with warehouse set
        data = get_product_info_for_website(item_code,
                                            skip_quotation_creation=True)
        self.assertTrue(bool(data.product_info["in_stock"]))
        self.assertEqual(data.product_info["stock_qty"][0][0], 2)

        # unset warehouse
        frappe.db.set_value("Website Item", {"item_code": item_code},
                            "website_warehouse", "")

        # check if stock details are fetched and item not in stock without warehouse set
        # (even though it has stock in some warehouse)
        data = get_product_info_for_website(item_code,
                                            skip_quotation_creation=True)
        self.assertFalse(bool(data.product_info["in_stock"]))
        self.assertFalse(bool(data.product_info["stock_qty"]))

        # disable show stock availability
        setup_e_commerce_settings({"show_stock_availability": 0})
        frappe.local.shopping_cart_settings = None
        data = get_product_info_for_website(item_code,
                                            skip_quotation_creation=True)

        # check if stock detail attributes are not fetched if stock availability is hidden
        self.assertIsNone(data.product_info.get("in_stock"))
        self.assertIsNone(data.product_info.get("stock_qty"))
        self.assertIsNone(data.product_info.get("show_stock_qty"))

        # tear down
        stock_entry.cancel()
        frappe.get_cached_doc("Website Item", {
            "item_code": "Test Mobile Phone"
        }).delete()
    def test_consolidation_rounding_adjustment(self):
        """
		Test if the rounding adjustment is calculated correctly
		"""
        frappe.db.sql("delete from `tabPOS Invoice`")

        try:
            make_stock_entry(
                to_warehouse="_Test Warehouse - _TC",
                item_code="_Test Item",
                rate=8000,
                qty=10,
            )

            init_user_and_profile()

            inv = create_pos_invoice(qty=1, rate=69.5, do_not_save=True)
            inv.append("payments", {
                "mode_of_payment": "Cash",
                "account": "Cash - _TC",
                "amount": 70
            })
            inv.insert()
            inv.submit()

            inv2 = create_pos_invoice(qty=1, rate=59.5, do_not_save=True)
            inv2.append("payments", {
                "mode_of_payment": "Cash",
                "account": "Cash - _TC",
                "amount": 60
            })
            inv2.insert()
            inv2.submit()

            consolidate_pos_invoices()

            inv.load_from_db()
            consolidated_invoice = frappe.get_doc("Sales Invoice",
                                                  inv.consolidated_invoice)
            self.assertEqual(consolidated_invoice.rounding_adjustment, 1)

        finally:
            frappe.set_user("Administrator")
            frappe.db.sql("delete from `tabPOS Profile`")
            frappe.db.sql("delete from `tabPOS Invoice`")
Beispiel #32
0
def new_item(item_name,
             item_group,
             strain,
             actual_qty,
             default_warehouse,
             plant=None):
    item_group = frappe.get_doc("Item Group", item_group)
    location = frappe.get_value("BioTrack Settings", None, "location")

    call_data = {
        "invtype": item_group.external_id,
        "quantity": actual_qty,
        "strain": strain,
    }

    if plant:
        call_data["source_id"] = plant

    data = biotrackthc_call("inventory_new",
                            data={
                                "data": call_data,
                                "location": location
                            })

    barcode = data['barcode_id'][0]
    item = frappe.new_doc("Item")
    item.update({
        "item_name": item_name,
        "item_code": barcode,
        "barcode": barcode,
        "item_group": item_group.name,
        "default_warehouse": default_warehouse,
        "strain": strain,
        "plant": plant,
        "stock_uom": "Gram",
        "is_stock_item": 1,
        "actual_qty": actual_qty,
    })

    item.insert()
    make_stock_entry(item_code=barcode,
                     target=default_warehouse,
                     qty=actual_qty)

    return item
Beispiel #33
0
	def test_customer_provided_parts_se(self):
		create_item(
			"CUST-0987", is_customer_provided_item=1, customer="_Test Customer", is_purchase_item=0
		)
		se = make_stock_entry(
			item_code="CUST-0987", purpose="Material Receipt", qty=4, to_warehouse="_Test Warehouse - _TC"
		)
		self.assertEqual(se.get("items")[0].allow_zero_valuation_rate, 1)
		self.assertEqual(se.get("items")[0].amount, 0)
Beispiel #34
0
	def test_item_merging(self):
		create_item("Test Item for Merging 1")
		create_item("Test Item for Merging 2")

		make_stock_entry(item_code="Test Item for Merging 1", target="_Test Warehouse - _TC",
			qty=1, rate=100)
		make_stock_entry(item_code="Test Item for Merging 2", target="_Test Warehouse 1 - _TC",
			qty=1, rate=100)

		rename_doc("Item", "Test Item for Merging 1", "Test Item for Merging 2", merge=True)

		self.assertFalse(frappe.db.exists("Item", "Test Item for Merging 1"))

		self.assertTrue(frappe.db.get_value("Bin",
			{"item_code": "Test Item for Merging 2", "warehouse": "_Test Warehouse - _TC"}))

		self.assertTrue(frappe.db.get_value("Bin",
			{"item_code": "Test Item for Merging 2", "warehouse": "_Test Warehouse 1 - _TC"}))
Beispiel #35
0
	def test_item_merging(self):
		create_item("Test Item for Merging 1")
		create_item("Test Item for Merging 2")

		make_stock_entry(item_code="Test Item for Merging 1", target="_Test Warehouse - _TC",
			qty=1, rate=100)
		make_stock_entry(item_code="Test Item for Merging 2", target="_Test Warehouse 1 - _TC",
			qty=1, rate=100)

		rename_doc("Item", "Test Item for Merging 1", "Test Item for Merging 2", merge=True)

		self.assertFalse(frappe.db.exists("Item", "Test Item for Merging 1"))

		self.assertTrue(frappe.db.get_value("Bin",
			{"item_code": "Test Item for Merging 2", "warehouse": "_Test Warehouse - _TC"}))

		self.assertTrue(frappe.db.get_value("Bin",
			{"item_code": "Test Item for Merging 2", "warehouse": "_Test Warehouse 1 - _TC"}))
Beispiel #36
0
    def test_material_consumption(self):
        from erpnext.manufacturing.doctype.work_order.work_order \
         import make_stock_entry as _make_stock_entry
        bom_no = frappe.db.get_value("BOM", {
            "item": "_Test FG Item 2",
            "is_default": 1,
            "docstatus": 1
        })

        work_order = frappe.new_doc("Work Order")
        work_order.update({
            "company": "_Test Company",
            "fg_warehouse": "_Test Warehouse 1 - _TC",
            "production_item": "_Test FG Item 2",
            "bom_no": bom_no,
            "qty": 4.0,
            "stock_uom": "_Test UOM",
            "wip_warehouse": "_Test Warehouse - _TC",
            "additional_operating_cost": 1000
        })
        work_order.insert()
        work_order.submit()

        make_stock_entry(item_code="_Test Serialized Item With Series",
                         target="_Test Warehouse - _TC",
                         qty=50,
                         basic_rate=100)
        make_stock_entry(item_code="_Test Item 2",
                         target="_Test Warehouse - _TC",
                         qty=50,
                         basic_rate=20)

        item_quantity = {
            '_Test Item': 10.0,
            '_Test Item 2': 12.0,
            '_Test Serialized Item With Series': 6.0
        }

        stock_entry = frappe.get_doc(
            _make_stock_entry(work_order.name,
                              "Material Consumption for Manufacture", 10))
        for d in stock_entry.get('items'):
            if (item_quantity.get(d.item_code)):
                self.assertEqual(item_quantity.get(d.item_code), d.qty)
Beispiel #37
0
    def test_material_transfer_gl_entry(self):
        company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company')

        item_code = 'Hand Sanitizer - 001'
        create_item(item_code=item_code,
                    is_stock_item=1,
                    is_purchase_item=1,
                    opening_stock=1000,
                    valuation_rate=10,
                    company=company,
                    warehouse="Stores - TCP1")

        mtn = make_stock_entry(item_code=item_code,
                               source="Stores - TCP1",
                               target="Finished Goods - TCP1",
                               qty=45,
                               company=company)

        self.check_stock_ledger_entries(
            "Stock Entry", mtn.name,
            [[item_code, "Stores - TCP1", -45.0],
             [item_code, "Finished Goods - TCP1", 45.0]])

        source_warehouse_account = get_inventory_account(
            mtn.company,
            mtn.get("items")[0].s_warehouse)

        target_warehouse_account = get_inventory_account(
            mtn.company,
            mtn.get("items")[0].t_warehouse)

        if source_warehouse_account == target_warehouse_account:
            # no gl entry as both source and target warehouse has linked to same account.
            self.assertFalse(
                frappe.db.sql("""select * from `tabGL Entry`
				where voucher_type='Stock Entry' and voucher_no=%s""",
                              mtn.name,
                              as_dict=1))

        else:
            stock_value_diff = abs(
                frappe.db.get_value(
                    "Stock Ledger Entry", {
                        "voucher_type": "Stock Entry",
                        "voucher_no": mtn.name,
                        "warehouse": "Stores - TCP1"
                    }, "stock_value_difference"))

            self.check_gl_entries(
                "Stock Entry", mtn.name,
                sorted([
                    [source_warehouse_account, 0.0, stock_value_diff],
                    [target_warehouse_account, stock_value_diff, 0.0],
                ]))

        mtn.cancel()
Beispiel #38
0
	def test_multi_batch_value_diff(self):
		"""Test value difference on stock entry in case of multi-batch.
		| Stock entry | batch | qty | rate | value diff on SE             |
		| ---         | ---   | --- | ---  | ---                          |
		| receipt     | A     | 1   | 10   | 30                           |
		| receipt     | B     | 1   | 20   |                              |
		| issue       | A     | -1  | 10   | -30 (to assert after submit) |
		| issue       | B     | -1  | 20   |                              |
		"""
		from erpnext.stock.doctype.batch.test_batch import TestBatch

		batch_nos = []

		item_code = "_TestMultibatchFifo"
		TestBatch.make_batch_item(item_code)
		warehouse = "_Test Warehouse - _TC"
		receipt = make_stock_entry(
			item_code=item_code,
			qty=1,
			rate=10,
			to_warehouse=warehouse,
			purpose="Material Receipt",
			do_not_save=True,
		)
		receipt.append(
			"items", frappe.copy_doc(receipt.items[0], ignore_no_copy=False).update({"basic_rate": 20})
		)
		receipt.save()
		receipt.submit()
		batch_nos.extend(row.batch_no for row in receipt.items)
		self.assertEqual(receipt.value_difference, 30)

		issue = make_stock_entry(
			item_code=item_code, qty=1, from_warehouse=warehouse, purpose="Material Issue", do_not_save=True
		)
		issue.append("items", frappe.copy_doc(issue.items[0], ignore_no_copy=False))
		for row, batch_no in zip(issue.items, batch_nos):
			row.batch_no = batch_no
		issue.save()
		issue.submit()

		issue.reload()  # reload because reposting current voucher updates rate
		self.assertEqual(issue.value_difference, -30)
    def test_fifo_dependent_consumption(self):
        item = make_item("_TestFifoTransferRates")
        source = "_Test Warehouse - _TC"
        target = "Stores - _TC"

        rates = [10 * i for i in range(1, 20)]

        receipt = make_stock_entry(item_code=item.name,
                                   target=source,
                                   qty=10,
                                   do_not_save=True,
                                   rate=10)
        for rate in rates[1:]:
            row = frappe.copy_doc(receipt.items[0], ignore_no_copy=False)
            row.basic_rate = rate
            receipt.append("items", row)

        receipt.save()
        receipt.submit()

        expected_queues = []
        for idx, rate in enumerate(rates, start=1):
            expected_queues.append(
                {"stock_queue": [[10, 10 * i] for i in range(1, idx + 1)]})
        self.assertSLEs(receipt, expected_queues)

        transfer = make_stock_entry(item_code=item.name,
                                    source=source,
                                    target=target,
                                    qty=10,
                                    do_not_save=True,
                                    rate=10)
        for rate in rates[1:]:
            row = frappe.copy_doc(transfer.items[0], ignore_no_copy=False)
            transfer.append("items", row)

        transfer.save()
        transfer.submit()

        # same exact queue should be transferred
        self.assertSLEs(transfer,
                        expected_queues,
                        sle_filters={"warehouse": target})
Beispiel #40
0
	def test_repack_multiple_fg(self):
		"Test `is_finished_item` for one item repacked into two items."
		make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=100, basic_rate=100)

		repack = frappe.copy_doc(test_records[3])
		repack.posting_date = nowdate()
		repack.posting_time = nowtime()

		repack.items[0].qty = 100.0
		repack.items[0].transfer_qty = 100.0
		repack.items[1].qty = 50.0

		repack.append(
			"items",
			{
				"conversion_factor": 1.0,
				"cost_center": "_Test Cost Center - _TC",
				"doctype": "Stock Entry Detail",
				"expense_account": "Stock Adjustment - _TC",
				"basic_rate": 150,
				"item_code": "_Test Item 2",
				"parentfield": "items",
				"qty": 50.0,
				"stock_uom": "_Test UOM",
				"t_warehouse": "_Test Warehouse - _TC",
				"transfer_qty": 50.0,
				"uom": "_Test UOM",
			},
		)
		repack.set_stock_entry_type()
		repack.insert()

		self.assertEqual(repack.items[1].is_finished_item, 1)
		self.assertEqual(repack.items[2].is_finished_item, 1)

		repack.items[1].is_finished_item = 0
		repack.items[2].is_finished_item = 0

		# must raise error if 0 fg in repack entry
		self.assertRaises(FinishedGoodError, repack.validate_finished_goods)

		repack.delete()  # teardown
	def test_repack_with_additional_costs(self):
		set_perpetual_inventory()

		make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, basic_rate=100)
		repack = frappe.copy_doc(test_records[3])
		repack.posting_date = nowdate()
		repack.posting_time = nowtime()

		repack.set("additional_costs", [
			{
				"description": "Actual Oerating Cost",
				"amount": 1000
			},
			{
				"description": "additional operating costs",
				"amount": 200
			},
		])
		repack.insert()
		repack.submit()

		stock_in_hand_account = frappe.db.get_value("Account", {"account_type": "Warehouse",
			"warehouse": repack.get("items")[1].t_warehouse})

		rm_stock_value_diff = abs(frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Stock Entry",
			"voucher_no": repack.name, "item_code": "_Test Item"}, "stock_value_difference"))

		fg_stock_value_diff = abs(frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Stock Entry",
			"voucher_no": repack.name, "item_code": "_Test Item Home Desktop 100"}, "stock_value_difference"))

		stock_value_diff = flt(fg_stock_value_diff - rm_stock_value_diff, 2)

		self.assertEqual(stock_value_diff, 1200)

		self.check_gl_entries("Stock Entry", repack.name,
			sorted([
				[stock_in_hand_account, 1200, 0.0],
				["Expenses Included In Valuation - _TC", 0.0, 1200.0]
			])
		)
		set_perpetual_inventory(0)
Beispiel #42
0
	def set_opening_stock(self):
		'''set opening stock'''
		from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry

		# default warehouse, or Stores
		default_warehouse = (frappe.db.get_single_value('Stock Settings', 'default_warehouse')
			or frappe.db.get_value('Warehouse', {'warehouse_name': _('Stores')}))

		if default_warehouse:
			stock_entry = make_stock_entry(item_code=self.name,
				target=default_warehouse,
				qty=self.opening_stock)

			stock_entry.add_comment("Comment", _("Opening Stock"))
	def test_repack_no_change_in_valuation(self):
		set_perpetual_inventory(0)

		make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, basic_rate=100)
		make_stock_entry(item_code="_Test Item Home Desktop 100", target="_Test Warehouse - _TC",
			qty=50, basic_rate=100)

		repack = frappe.copy_doc(test_records[3])
		repack.posting_date = nowdate()
		repack.posting_time = nowtime()
		repack.insert()
		repack.submit()

		self.check_stock_ledger_entries("Stock Entry", repack.name,
			[["_Test Item", "_Test Warehouse - _TC", -50.0],
				["_Test Item Home Desktop 100", "_Test Warehouse - _TC", 1]])

		gl_entries = frappe.db.sql("""select account, debit, credit
			from `tabGL Entry` where voucher_type='Stock Entry' and voucher_no=%s
			order by account desc""", repack.name, as_dict=1)
		self.assertFalse(gl_entries)

		set_perpetual_inventory(0)
Beispiel #44
0
	def test_fifo(self):
		frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1)
		item_code = "_Test Item 2"
		warehouse = "_Test Warehouse - _TC"

		create_stock_reconciliation(item_code="_Test Item 2", warehouse="_Test Warehouse - _TC",
			qty=0, rate=100)

		make_stock_entry(item_code=item_code, target=warehouse, qty=1, basic_rate=10)
		sle = get_sle(item_code = item_code, warehouse = warehouse)[0]

		self.assertEqual([[1, 10]], frappe.safe_eval(sle.stock_queue))

		# negative qty
		make_stock_entry(item_code=item_code, source=warehouse, qty=2, basic_rate=10)
		sle = get_sle(item_code = item_code, warehouse = warehouse)[0]

		self.assertEqual([[-1, 10]], frappe.safe_eval(sle.stock_queue))

		# further negative
		make_stock_entry(item_code=item_code, source=warehouse, qty=1)
		sle = get_sle(item_code = item_code, warehouse = warehouse)[0]

		self.assertEqual([[-2, 10]], frappe.safe_eval(sle.stock_queue))

		# move stock to positive
		make_stock_entry(item_code=item_code, target=warehouse, qty=3, basic_rate=20)
		sle = get_sle(item_code = item_code, warehouse = warehouse)[0]
		self.assertEqual([[1, 20]], frappe.safe_eval(sle.stock_queue))

		# incoming entry with diff rate
		make_stock_entry(item_code=item_code, target=warehouse, qty=1, basic_rate=30)
		sle = get_sle(item_code = item_code, warehouse = warehouse)[0]

		self.assertEqual([[1, 20],[1, 30]], frappe.safe_eval(sle.stock_queue))

		frappe.db.set_default("allow_negative_stock", 0)
Beispiel #45
0
	def set_opening_stock(self):
		'''set opening stock'''
		if not self.is_stock_item or self.has_serial_no or self.has_batch_no:
			return
		
		if not self.valuation_rate:
			frappe.throw(_("Valuation Rate is mandatory if Opening Stock entered"))

		from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry

		# default warehouse, or Stores
		default_warehouse = (frappe.db.get_single_value('Stock Settings', 'default_warehouse')
			or frappe.db.get_value('Warehouse', {'warehouse_name': _('Stores')}))

		if default_warehouse:
			stock_entry = make_stock_entry(item_code=self.name, target=default_warehouse,
				qty=self.opening_stock, rate=self.valuation_rate)

			stock_entry.add_comment("Comment", _("Opening Stock"))
	def test_same_serial_nos_in_repack_or_manufacture_entries(self):
		s1 = make_serialized_item(target_warehouse="_Test Warehouse - _TC")
		serial_nos = s1.get("items")[0].serial_no

		s2 = make_stock_entry(item_code="_Test Serialized Item With Series", source="_Test Warehouse - _TC",
			qty=2, basic_rate=100, purpose="Repack", serial_no=serial_nos, do_not_save=True)

		s2.append("items", {
			"item_code": "_Test Serialized Item",
			"t_warehouse": "_Test Warehouse - _TC",
			"qty": 2,
			"basic_rate": 120,
			"expense_account": "Stock Adjustment - _TC",
			"conversion_factor": 1.0,
			"cost_center": "_Test Cost Center - _TC",
			"serial_no": serial_nos
		})

		s2.submit()
		s2.cancel()
	def test_variant_production_order(self):
		bom_no = frappe.db.get_value("BOM", {"item": "_Test Variant Item",
			"is_default": 1, "docstatus": 1})

		production_order = frappe.new_doc("Production Order")
		production_order.update({
			"company": "_Test Company",
			"fg_warehouse": "_Test Warehouse 1 - _TC",
			"production_item": "_Test Variant Item-S",
			"bom_no": bom_no,
			"qty": 1.0,
			"stock_uom": "_Test UOM",
			"wip_warehouse": "_Test Warehouse - _TC"
		})
		production_order.insert()
		production_order.submit()

		from erpnext.manufacturing.doctype.production_order.production_order import make_stock_entry

		stock_entry = frappe.get_doc(make_stock_entry(production_order.name, "Manufacture", 1))
		stock_entry.insert()
		self.assertTrue("_Test Variant Item-S" in [d.item_code for d in stock_entry.items])
Beispiel #48
0
	def test_material_transfer_gl_entry(self):
		company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company')
		set_perpetual_inventory(1, company)

		create_stock_reconciliation(qty=100, rate=100)

		mtn = make_stock_entry(item_code="_Test Item", source="_Test Warehouse - _TC",
			target="_Test Warehouse 1 - _TC", qty=45)

		self.check_stock_ledger_entries("Stock Entry", mtn.name,
			[["_Test Item", "_Test Warehouse - _TC", -45.0], ["_Test Item", "_Test Warehouse 1 - _TC", 45.0]])

		stock_in_hand_account = get_inventory_account(mtn.company, mtn.get("items")[0].s_warehouse)

		fixed_asset_account = get_inventory_account(mtn.company, mtn.get("items")[0].t_warehouse)

		if stock_in_hand_account == fixed_asset_account:
			# no gl entry as both source and target warehouse has linked to same account.
			self.assertFalse(frappe.db.sql("""select * from `tabGL Entry`
				where voucher_type='Stock Entry' and voucher_no=%s""", mtn.name))

		else:
			stock_value_diff = abs(frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Stock Entry",
				"voucher_no": mtn.name, "warehouse": "_Test Warehouse - _TC"}, "stock_value_difference"))

			self.check_gl_entries("Stock Entry", mtn.name,
				sorted([
					[stock_in_hand_account, 0.0, stock_value_diff],
					[fixed_asset_account, stock_value_diff, 0.0],
				])
			)

		mtn.cancel()
		self.assertFalse(frappe.db.sql("""select * from `tabStock Ledger Entry`
			where voucher_type='Stock Entry' and voucher_no=%s""", mtn.name))

		self.assertFalse(frappe.db.sql("""select * from `tabGL Entry`
			where voucher_type='Stock Entry' and voucher_no=%s""", mtn.name))
Beispiel #49
0
	def test_serial_no_based_delivery(self):
		frappe.set_value("Stock Settings", None, "automatically_set_serial_nos_based_on_fifo", 1)
		from erpnext.stock.doctype.item.test_item import make_item
		item = make_item("_Reserved_Serialized_Item", {"is_stock_item": 1,
					"maintain_stock": 1,
					"has_serial_no": 1,
					"serial_no_series": "SI.####",
					"valuation_rate": 500,
					"item_defaults": [
						{
							"default_warehouse": "_Test Warehouse - _TC",
							"company": "_Test Company"
						}]
					})
		frappe.db.sql("""delete from `tabSerial No` where item_code=%s""", (item.item_code))
		make_item("_Test Item A", {"maintain_stock": 1,
					"valuation_rate": 100,
					"item_defaults": [
						{
							"default_warehouse": "_Test Warehouse - _TC",
							"company": "_Test Company"
						}]
					})
		make_item("_Test Item B", {"maintain_stock": 1,
					"valuation_rate": 200,
					"item_defaults": [
						{
							"default_warehouse": "_Test Warehouse - _TC",
							"company": "_Test Company"
						}]
					})
		from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom
		make_bom(item=item.item_code, rate=1000,
			raw_materials = ['_Test Item A', '_Test Item B'])

		so = make_sales_order(**{
			"item_list": [{
				"item_code": item.item_code,
				"ensure_delivery_based_on_produced_serial_no": 1,
				"qty": 1,
				"rate":1000
			}]
		})
		so.submit()
		from erpnext.manufacturing.doctype.work_order.test_work_order import \
			make_wo_order_test_record
		work_order = make_wo_order_test_record(item=item.item_code,
			qty=1, do_not_save=True)
		work_order.fg_warehouse = "_Test Warehouse - _TC"
		work_order.sales_order = so.name
		work_order.submit()
		make_stock_entry(item_code=item.item_code, target="_Test Warehouse - _TC", qty=1)
		item_serial_no = frappe.get_doc("Serial No", {"item_code": item.item_code})
		from erpnext.manufacturing.doctype.work_order.work_order import \
			make_stock_entry as make_production_stock_entry
		se = frappe.get_doc(make_production_stock_entry(work_order.name, "Manufacture", 1))
		se.submit()
		reserved_serial_no = se.get("items")[2].serial_no
		serial_no_so = frappe.get_value("Serial No", reserved_serial_no, "sales_order")
		self.assertEqual(serial_no_so, so.name)
		dn = make_delivery_note(so.name)
		dn.save()
		self.assertEqual(reserved_serial_no, dn.get("items")[0].serial_no)
		item_line = dn.get("items")[0]
		item_line.serial_no = item_serial_no.name
		self.assertRaises(frappe.ValidationError, dn.submit)
		item_line = dn.get("items")[0]
		item_line.serial_no =  reserved_serial_no
		self.assertTrue(dn.submit)
		dn.load_from_db()
		dn.cancel()
		si = make_sales_invoice(so.name)
		si.update_stock = 1
		si.save()
		self.assertEqual(si.get("items")[0].serial_no, reserved_serial_no)
		item_line = si.get("items")[0]
		item_line.serial_no = item_serial_no.name
		self.assertRaises(frappe.ValidationError, dn.submit)
		item_line = si.get("items")[0]
		item_line.serial_no = reserved_serial_no
		self.assertTrue(si.submit)
		si.submit()
		si.load_from_db()
		si.cancel()
		si = make_sales_invoice(so.name)
		si.update_stock = 0
		si.submit()
		from erpnext.accounts.doctype.sales_invoice.sales_invoice import \
			make_delivery_note as make_delivery_note_from_invoice
		dn = make_delivery_note_from_invoice(si.name)
		dn.save()
		dn.submit()
		self.assertEqual(dn.get("items")[0].serial_no, reserved_serial_no)
		dn.load_from_db()
		dn.cancel()
		si.load_from_db()
		si.cancel()
		se.load_from_db()
		se.cancel()
		self.assertFalse(frappe.db.exists("Serial No", {"sales_order": so.name}))
Beispiel #50
0
def sync_item(data):
	barcode = str(data.get("id"))
	remaining_quantity = flt(data.get("remaining_quantity"))
	name = None

	item_values = get_item_values(barcode, ["name", "transaction_id"])
	if item_values:
		name, transaction_id = item_values
		if not (frappe.flags.force_sync or False) and transaction_id == data.get("transactionid"):
			frappe.db.set_value("Item", name, "bio_last_sync", now(), update_modified=False)
			return False

	# inventory type
	item_group = find_item_group(data)
	warehouse = find_warehouse(data)
	current_remaining_quantity = 0

	# product (Item) mapping
	if data.get("productname"):
		item_name = data.get("productname")
	else:
		item_name = " ".join(filter(None, [data.get("strain"), item_group.name]))

	if not name:
		item_code = barcode
		item = frappe.get_doc({
			"doctype": "Item",
			"item_code": item_code,
			"item_name": item_name,
			"bio_barcode": barcode,
			"is_stock_item": 1,
			"stock_uom": "Gram",
			"item_group": item_group.name,
			"default_warehouse": warehouse.name,
		})
	else:
		item = frappe.get_doc("Item", name)
		current_remaining_quantity = item.bio_remaining_quantity

	strain = ""
	if data.get("strain"):
		strain = find_strain(data.get("strain"))

	# Post task will do on biotrack_after_sync hook
	parent_ids = data.get("parentid")
	plant_ids = data.get("plantid")
	if not item.is_lot_item and (parent_ids or plant_ids):
		item.set("linking_data", json.dumps({"parent_ids": parent_ids, "plant_ids": plant_ids}))

	item.update({
		"item_name": item_name,
		"bio_barcode": barcode,
		"strain": strain,
		"bio_remaining_quantity": remaining_quantity,
		"transaction_id": data.get("transactionid"),
		"bio_last_sync": now(),
		"disabled": 1 if remaining_quantity == 0 else 0,
	})

	item.flags.ignore_links = True
	item.save()

	# adjust_stock
	if item.is_stock_item:
		if remaining_quantity > current_remaining_quantity:
			make_stock_entry(item_code=item.name, target=item.default_warehouse, qty=remaining_quantity - current_remaining_quantity)

		# Consider to not modified down item's balance because it's hard to figure out the correct warehouse and its balance to deduct
		# elif remaining_quantity < current_remaining_quantity:
		# 	posting_date, posting_time = nowdate(), nowtime()
		# 	balance = get_stock_balance_for(item.name, item.default_warehouse, posting_date, posting_time)
		#
		# 	if balance["qty"] >= remaining_quantity:
		# 		make_stock_entry(item_code=item.name, source=item.default_warehouse,
		# 					 qty=current_remaining_quantity - remaining_quantity)

	# Disable Usable Marijuana item does not have product name
	if not data.get("productname") and item_group.external_id == 28:
		frappe.db.set_value("Item", item.name, "disabled", 1)
		log_invalid_item(item)

	frappe.db.commit()

	return True
Beispiel #51
0
	def make_stock_entry(self):
		item = frappe.get_doc("Item", self.get("item_code"))
		ste = make_stock_entry(item_code=item.name, source=self.get_source_warehouse(), qty=self.qty, do_not_save=True)
		ste.plant = self.name
		ste.submit()
	def test_drop_shipping(self):
		from erpnext.selling.doctype.sales_order.sales_order import make_purchase_order_for_drop_shipment
		from erpnext.stock.doctype.item.test_item import make_item
		from erpnext.buying.doctype.purchase_order.purchase_order import update_status

		make_stock_entry(target="_Test Warehouse - _TC", qty=10, rate=100)
		
		po_item = make_item("_Test Item for Drop Shipping", {"is_stock_item": 1, "delivered_by_supplier": 1,
        'default_supplier': '_Test Supplier',
		    "expense_account": "_Test Account Cost for Goods Sold - _TC",
		    "cost_center": "_Test Cost Center - _TC"
			})

		dn_item = make_item("_Test Regular Item", {"is_stock_item": 1, "expense_account": "_Test Account Cost for Goods Sold - _TC",
  		  	"cost_center": "_Test Cost Center - _TC"})

		so_items = [
			{
				"item_code": po_item.item_code,
				"warehouse": "",
				"qty": 2,
				"rate": 400,
				"delivered_by_supplier": 1,
				"supplier": '_Test Supplier'
			},
			{
				"item_code": dn_item.item_code,
				"warehouse": "_Test Warehouse - _TC",
				"qty": 2,
				"rate": 300,
				"conversion_factor": 1.0
			}
		]

		if frappe.db.get_value("Item", "_Test Regular Item", "is_stock_item")==1:
			make_stock_entry(item="_Test Regular Item", target="_Test Warehouse - _TC", qty=10, rate=100)

		#setuo existing qty from bin
		bin = frappe.get_all("Bin", filters={"item_code": po_item.item_code, "warehouse": "_Test Warehouse - _TC"},
			fields=["ordered_qty", "reserved_qty"])

		existing_ordered_qty = bin[0].ordered_qty if bin else 0.0
		existing_reserved_qty = bin[0].reserved_qty if bin else 0.0

		bin = frappe.get_all("Bin", filters={"item_code": dn_item.item_code,
			"warehouse": "_Test Warehouse - _TC"}, fields=["reserved_qty"])

		existing_reserved_qty_for_dn_item = bin[0].reserved_qty if bin else 0.0

		#create so, po and partial dn
		so = make_sales_order(item_list=so_items, do_not_submit=True)
		so.submit()

		po = make_purchase_order_for_drop_shipment(so.name, '_Test Supplier')
		po.submit()

		dn = create_dn_against_so(so.name, delivered_qty=1)

		self.assertEquals(so.customer, po.customer)
		self.assertEquals(po.items[0].sales_order, so.name)
		self.assertEquals(po.items[0].item_code, po_item.item_code)
		self.assertEquals(dn.items[0].item_code, dn_item.item_code)

		#test ordered_qty and reserved_qty
		bin = frappe.get_all("Bin", filters={"item_code": po_item.item_code, "warehouse": "_Test Warehouse - _TC"},
			fields=["ordered_qty", "reserved_qty"])

		ordered_qty = bin[0].ordered_qty if bin else 0.0
		reserved_qty = bin[0].reserved_qty if bin else 0.0

		self.assertEquals(abs(flt(ordered_qty)), existing_ordered_qty)
		self.assertEquals(abs(flt(reserved_qty)), existing_reserved_qty)

		reserved_qty = frappe.db.get_value("Bin",
					{"item_code": dn_item.item_code, "warehouse": "_Test Warehouse - _TC"}, "reserved_qty")

		self.assertEquals(abs(flt(reserved_qty)), existing_reserved_qty_for_dn_item + 1)

		#test po_item length
		self.assertEquals(len(po.items), 1)

		#test per_delivered status
		update_status("Delivered", po.name)
		self.assertEquals(flt(frappe.db.get_value("Sales Order", so.name, "per_delivered"), 2), 75.00)

		#test reserved qty after complete delivery
		dn = create_dn_against_so(so.name, delivered_qty=1)
		reserved_qty = frappe.db.get_value("Bin",
			{"item_code": dn_item.item_code, "warehouse": "_Test Warehouse - _TC"}, "reserved_qty")

		self.assertEquals(abs(flt(reserved_qty)), existing_reserved_qty_for_dn_item)

		#test after closing so
		so.db_set('status', "Closed")
		so.update_reserved_qty()

		bin = frappe.get_all("Bin", filters={"item_code": po_item.item_code, "warehouse": "_Test Warehouse - _TC"},
			fields=["ordered_qty", "reserved_qty"])

		ordered_qty = bin[0].ordered_qty if bin else 0.0
		reserved_qty = bin[0].reserved_qty if bin else 0.0

		self.assertEquals(abs(flt(ordered_qty)), existing_ordered_qty)
		self.assertEquals(abs(flt(reserved_qty)), existing_reserved_qty)

		reserved_qty = frappe.db.get_value("Bin",
			{"item_code": dn_item.item_code, "warehouse": "_Test Warehouse - _TC"}, "reserved_qty")

		self.assertEquals(abs(flt(reserved_qty)), existing_reserved_qty_for_dn_item)