def test_not_accept_duplicate_serial_no(self):
        from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
        from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note

        item_code = frappe.db.get_value('Item', {
            'has_serial_no': 1,
            'is_fixed_asset': 0
        })
        if not item_code:
            item = make_item("Test Serial Item 1", dict(has_serial_no=1))
            item_code = item.name

        serial_no = random_string(5)
        make_purchase_receipt(item_code=item_code, qty=1, serial_no=serial_no)
        create_delivery_note(item_code=item_code, qty=1, serial_no=serial_no)

        pr = make_purchase_receipt(item_code=item_code,
                                   qty=1,
                                   serial_no=serial_no,
                                   do_not_submit=True)
        self.assertRaises(SerialNoDuplicateError, pr.submit)

        se = make_stock_entry(item_code=item_code,
                              target="_Test Warehouse - _TC",
                              qty=1,
                              serial_no=serial_no,
                              basic_rate=100,
                              do_not_submit=True)
        self.assertRaises(SerialNoDuplicateError, se.submit)
Пример #2
0
	def test_inter_company_transfer(self):
		se = make_serialized_item(target_warehouse="_Test Warehouse - _TC")
		serial_nos = get_serial_nos(se.get("items")[0].serial_no)

		create_delivery_note(item_code="_Test Serialized Item With Series", qty=1, serial_no=serial_nos[0])

		wh = create_warehouse("_Test Warehouse", company="_Test Company 1")
		make_purchase_receipt(item_code="_Test Serialized Item With Series", qty=1, serial_no=serial_nos[0],
			company="_Test Company 1", warehouse=wh)

		serial_no = frappe.db.get_value("Serial No", serial_nos[0], ["warehouse", "company"], as_dict=1)

		self.assertEqual(serial_no.warehouse, wh)
		self.assertEqual(serial_no.company, "_Test Company 1")
Пример #3
0
	def _test_delivery_note_return(self, item_code, delivered_qty, returned_qty):
		from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note

		from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice

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

		actual_qty_0 = get_qty_after_transaction()
		# make a delivery note based on this invoice
		dn = create_delivery_note(item_code="_Test Item",
			warehouse="_Test Warehouse - _TC", qty=delivered_qty)

		actual_qty_1 = get_qty_after_transaction()

		self.assertEquals(actual_qty_0 - delivered_qty, actual_qty_1)

		si = make_sales_invoice(dn.name)
		si.insert()
		si.submit()

		# insert and submit stock entry for sales return
		se = make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC",
			qty=returned_qty, purpose="Sales Return", delivery_note_no=dn.name)

		actual_qty_2 = get_qty_after_transaction()
		self.assertEquals(actual_qty_1 + returned_qty, actual_qty_2)

		return se
    def test_qa_for_delivery(self):
        make_stock_entry(item_code="_Test Item with QA",
                         target="_Test Warehouse - _TC",
                         qty=1,
                         basic_rate=100)
        dn = create_delivery_note(item_code="_Test Item with QA",
                                  do_not_submit=True)

        self.assertRaises(QualityInspectionRequiredError, dn.submit)

        qa = create_quality_inspection(reference_type="Delivery Note",
                                       reference_name=dn.name,
                                       status="Rejected")
        dn.reload()
        self.assertRaises(QualityInspectionRejectedError, dn.submit)

        frappe.db.set_value("Quality Inspection", qa.name, "status",
                            "Accepted")
        dn.reload()
        dn.submit()

        qa.reload()
        qa.cancel()
        dn.reload()
        dn.cancel()
Пример #5
0
	def test_value_based_qi_readings(self):
		# Test QI based on acceptance values (Non formula)
		dn = create_delivery_note(item_code="_Test Item with QA", do_not_submit=True)
		readings = [
			{
				"specification": "Iron Content",  # numeric reading
				"min_value": 0.1,
				"max_value": 0.9,
				"reading_1": "0.4",
			},
			{
				"specification": "Particle Inspection Needed",  # non-numeric reading
				"numeric": 0,
				"value": "Yes",
				"reading_value": "Yes",
			},
		]

		qa = create_quality_inspection(
			reference_type="Delivery Note", reference_name=dn.name, readings=readings, do_not_save=True
		)

		qa.save()

		# status must be auto set as per formula
		self.assertEqual(qa.readings[0].status, "Accepted")
		self.assertEqual(qa.readings[1].status, "Accepted")

		qa.delete()
		dn.delete()
	def test_formula_based_qi_readings(self):
		dn = create_delivery_note(item_code="_Test Item with QA", do_not_submit=True)
		readings = [{
			"specification": "Iron Content",
			"acceptance_formula": "reading_1 > 0.35 and reading_1 < 0.50",
			"reading_1": 0.4
		},
		{
			"specification": "Calcium Content",
			"acceptance_formula": "reading_1 > 0.20 and reading_1 < 0.50",
			"reading_1": 0.7
		},
		{
			"specification": "Mg Content",
			"acceptance_formula": "(reading_1 + reading_2 + reading_3) / 3 < 0.9",
			"reading_1": 0.5,
			"reading_2": 0.7,
			"reading_3": "random text" # check if random string input causes issues
		}]

		qa = create_quality_inspection(reference_type="Delivery Note", reference_name=dn.name,
			readings=readings, do_not_save=True)
		qa.save()

		# status must be auto set as per formula
		self.assertEqual(qa.readings[0].status, "Accepted")
		self.assertEqual(qa.readings[1].status, "Rejected")
		self.assertEqual(qa.readings[2].status, "Accepted")

		qa.delete()
		dn.delete()
Пример #7
0
	def test_delivered_serial_no_case(self):
		from erpnext.accounts.doctype.pos_invoice_merge_log.test_pos_invoice_merge_log import (
			init_user_and_profile,
		)
		from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note
		from erpnext.stock.doctype.serial_no.test_serial_no import get_serial_nos
		from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item

		frappe.db.savepoint("before_test_delivered_serial_no_case")
		try:
			se = make_serialized_item()
			serial_no = get_serial_nos(se.get("items")[0].serial_no)[0]

			dn = create_delivery_note(item_code="_Test Serialized Item With Series", serial_no=serial_no)

			delivery_document_no = frappe.db.get_value("Serial No", serial_no, "delivery_document_no")
			self.assertEquals(delivery_document_no, dn.name)

			init_user_and_profile()

			pos_inv = create_pos_invoice(
				item_code="_Test Serialized Item With Series",
				serial_no=serial_no,
				qty=1,
				rate=100,
				do_not_submit=True,
			)

			self.assertRaises(frappe.ValidationError, pos_inv.submit)

		finally:
			frappe.db.rollback(save_point="before_test_delivered_serial_no_case")
			frappe.set_user("Administrator")
Пример #8
0
    def test_item_type_field_change(self):
        """Check if critical fields like `is_stock_item`, `has_batch_no` are not changed if transactions exist."""
        from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
        from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note
        from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt
        from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry

        transaction_creators = [
            lambda i: make_purchase_receipt(item_code=i),
            lambda i: make_purchase_invoice(item_code=i, update_stock=1),
            lambda i: make_stock_entry(
                item_code=i, qty=1, target="_Test Warehouse - _TC"),
            lambda i: create_delivery_note(item_code=i),
        ]

        properties = {
            "has_batch_no": 0,
            "allow_negative_stock": 1,
            "valuation_rate": 10
        }
        for transaction_creator in transaction_creators:
            item = make_item(properties=properties)
            transaction = transaction_creator(item.name)
            item.has_batch_no = 1
            self.assertRaises(frappe.ValidationError, item.save)

            transaction.cancel()
            # should be allowed now
            item.reload()
            item.has_batch_no = 1
            item.save()
Пример #9
0
    def test_inter_company_transfer(self):
        se = make_serialized_item(target_warehouse="_Test Warehouse - _TC")
        serial_nos = get_serial_nos(se.get("items")[0].serial_no)

        create_delivery_note(
            item_code="_Test Serialized Item With Series", qty=1, serial_no=serial_nos[0])

        wh = create_warehouse("_Test Warehouse", company="_Test Company 1")
        make_purchase_receipt(item_code="_Test Serialized Item With Series", qty=1, serial_no=serial_nos[0],
                              company="_Test Company 1", warehouse=wh)

        serial_no = frappe.db.get_value("Serial No", serial_nos[0], [
                                        "warehouse", "company"], as_dict=1)

        self.assertEqual(serial_no.warehouse, wh)
        self.assertEqual(serial_no.company, "_Test Company 1")
Пример #10
0
	def _test_delivery_note_return(self, item_code, delivered_qty, returned_qty):
		from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note

		from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice

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

		actual_qty_0 = get_qty_after_transaction()
		# make a delivery note based on this invoice
		dn = create_delivery_note(item_code="_Test Item",
			warehouse="_Test Warehouse - _TC", qty=delivered_qty)

		actual_qty_1 = get_qty_after_transaction()

		self.assertEquals(actual_qty_0 - delivered_qty, actual_qty_1)

		si = make_sales_invoice(dn.name)
		si.insert()
		si.submit()

		# insert and submit stock entry for sales return
		se = make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC",
			qty=returned_qty, purpose="Sales Return", delivery_note_no=dn.name)

		actual_qty_2 = get_qty_after_transaction()
		self.assertEquals(actual_qty_1 + returned_qty, actual_qty_2)

		return se
Пример #11
0
    def test_inter_company_transfer(self):
        se = make_serialized_item(target_warehouse="_Test Warehouse - _TC")
        serial_nos = get_serial_nos(se.get("items")[0].serial_no)

        dn = create_delivery_note(
            item_code="_Test Serialized Item With Series",
            qty=1,
            serial_no=serial_nos[0])

        serial_no = frappe.get_doc("Serial No", serial_nos[0])

        # check Serial No details after delivery
        self.assertEqual(serial_no.status, "Delivered")
        self.assertEqual(serial_no.warehouse, None)
        self.assertEqual(serial_no.company, "_Test Company")
        self.assertEqual(serial_no.delivery_document_type, "Delivery Note")
        self.assertEqual(serial_no.delivery_document_no, dn.name)

        wh = create_warehouse("_Test Warehouse", company="_Test Company 1")
        pr = make_purchase_receipt(
            item_code="_Test Serialized Item With Series",
            qty=1,
            serial_no=serial_nos[0],
            company="_Test Company 1",
            warehouse=wh)

        serial_no.reload()

        # check Serial No details after purchase in second company
        self.assertEqual(serial_no.status, "Active")
        self.assertEqual(serial_no.warehouse, wh)
        self.assertEqual(serial_no.company, "_Test Company 1")
        self.assertEqual(serial_no.purchase_document_type, "Purchase Receipt")
        self.assertEqual(serial_no.purchase_document_no, pr.name)
Пример #12
0
 def test_qa_not_submit(self):
     dn = create_delivery_note(item_code="_Test Item with QA",
                               do_not_submit=True)
     qa = create_quality_inspection(reference_type="Delivery Note",
                                    reference_name=dn.name,
                                    submit=False)
     dn.items[0].quality_inspection = qa.name
     self.assertRaises(QualityInspectionNotSubmittedError, dn.submit)
Пример #13
0
	def test_not_accept_duplicate_serial_no(self):
		from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
		from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note

		item_code = frappe.db.get_value('Item', {'has_serial_no': 1})
		if not item_code:
			item = make_item("Test Serial Item 1", dict(has_serial_no=1))
			item_code = item.name

		serial_no = random_string(5)
		make_purchase_receipt(item_code=item_code, qty=1, serial_no=serial_no)
		create_delivery_note(item_code=item_code, qty=1, serial_no=serial_no)

		pr = make_purchase_receipt(item_code=item_code, qty=1, serial_no=serial_no, do_not_submit=True)
		self.assertRaises(SerialNoDuplicateError, pr.submit)

		se = make_stock_entry(item_code=item_code, target="_Test Warehouse - _TC", qty=1,
			serial_no=serial_no, basic_rate=100, do_not_submit=True)
		self.assertRaises(SerialNoDuplicateError, se.submit)
Пример #14
0
	def test_qa_for_delivery(self):
		dn = create_delivery_note(item_code="_Test Item with QA", do_not_submit=True)
		self.assertRaises(QualityInspectionRequiredError, dn.submit)

		qa = create_quality_inspection(reference_type="Delivery Note", reference_name=dn.name, status="Rejected", submit=True)
		dn.reload()
		self.assertRaises(QualityInspectionRejectedError, dn.submit)

		frappe.db.set_value("Quality Inspection Reading", {"parent": qa.name}, "status", "Accepted")
		dn.reload()
		dn.submit()
Пример #15
0
	def test_make_quality_inspections_from_linked_document(self):
		dn = create_delivery_note(item_code="_Test Item with QA", do_not_submit=True)
		for item in dn.items:
			item.sample_size = item.qty
		quality_inspections = make_quality_inspections(dn.doctype, dn.name, dn.items)
		self.assertEqual(len(dn.items), len(quality_inspections))

		# cleanup
		for qi in quality_inspections:
			frappe.delete_doc("Quality Inspection", qi)
		dn.delete()
Пример #16
0
	def test_qa_for_delivery(self):
		dn = create_delivery_note(item_code="_Test Item with QA", do_not_submit=True, allow_zero_valuation=True)
		self.assertRaises(QualityInspectionRequiredError, dn.submit)

		qa = create_quality_inspection(reference_type="Delivery Note", reference_name=dn.name, status="Rejected", submit=True)
		dn.reload()
		self.assertRaises(QualityInspectionRejectedError, dn.submit)

		frappe.db.set_value("Quality Inspection Reading", {"parent": qa.name}, "status", "Accepted")
		dn.reload()
		dn.submit()
    def test_backdated_stock_reco_future_negative_stock(self):
        """
		Test if a backdated stock reco causes future negative stock and is blocked.
		-------------------------------------------
		Var		| Doc	|	Qty	| Balance
		-------------------------------------------
		PR1		| PR	|	10	|	10		(posting date: today-2)
		SR3		| Reco	|	0	|	1		(posting date: today-1) [backdated & blocked]
		DN2		| DN	|	-2	|	8(-1)	(posting date: today)
		"""
        from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note
        from erpnext.stock.stock_ledger import NegativeStockError

        item_code = make_item().name
        warehouse = "_Test Warehouse - _TC"

        pr1 = make_purchase_receipt(item_code=item_code,
                                    warehouse=warehouse,
                                    qty=10,
                                    rate=100,
                                    posting_date=add_days(nowdate(), -2))
        dn2 = create_delivery_note(item_code=item_code,
                                   warehouse=warehouse,
                                   qty=2,
                                   rate=120,
                                   posting_date=nowdate())

        pr1_balance = frappe.db.get_value("Stock Ledger Entry", {
            "voucher_no": pr1.name,
            "is_cancelled": 0
        }, "qty_after_transaction")
        dn2_balance = frappe.db.get_value("Stock Ledger Entry", {
            "voucher_no": dn2.name,
            "is_cancelled": 0
        }, "qty_after_transaction")
        self.assertEqual(pr1_balance, 10)
        self.assertEqual(dn2_balance, 8)

        # check if stock reco is blocked
        sr3 = create_stock_reconciliation(
            item_code=item_code,
            warehouse=warehouse,
            qty=1,
            rate=100,
            posting_date=add_days(nowdate(), -1),
            do_not_submit=True,
        )
        self.assertRaises(NegativeStockError, sr3.submit)

        # teardown
        sr3.cancel()
        dn2.cancel()
        pr1.cancel()
Пример #18
0
    def consume_item_code_with_differet_stock_transactions(
            self, item_code, warehouse="_Test Warehouse - _TC"):
        from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
        from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note
        from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt
        from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry

        typical_args = {"item_code": item_code, "warehouse": warehouse}

        create_delivery_note(**typical_args)
        create_sales_invoice(update_stock=1, **typical_args)
        make_stock_entry(item_code=item_code,
                         source=warehouse,
                         qty=1,
                         purpose="Material Issue")
        make_stock_entry(item_code=item_code,
                         source=warehouse,
                         target="Stores - _TC",
                         qty=1)
        # standalone return
        make_purchase_receipt(is_return=True, qty=-1, **typical_args)
Пример #19
0
    def test_formula_based_qi_readings(self):
        dn = create_delivery_note(item_code="_Test Item with QA",
                                  do_not_submit=True)
        readings = [
            {
                "specification": "Iron Content",  # numeric reading
                "formula_based_criteria": 1,
                "acceptance_formula": "reading_1 > 0.35 and reading_1 < 0.50",
                "reading_1": "0.4"
            },
            {
                "specification": "Calcium Content",  # numeric reading
                "formula_based_criteria": 1,
                "acceptance_formula": "reading_1 > 0.20 and reading_1 < 0.50",
                "reading_1": "0.7"
            },
            {
                "specification": "Mg Content",  # numeric reading
                "formula_based_criteria": 1,
                "acceptance_formula": "mean < 0.9",
                "reading_1": "0.5",
                "reading_2": "0.7",
                "reading_3":
                "random text"  # check if random string input causes issues
            },
            {
                "specification": "Calcium Content",  # non-numeric reading
                "formula_based_criteria": 1,
                "numeric": 0,
                "acceptance_formula":
                "reading_value in ('Grade A', 'Grade B', 'Grade C')",
                "reading_value": "Grade B"
            }
        ]

        qa = create_quality_inspection(reference_type="Delivery Note",
                                       reference_name=dn.name,
                                       readings=readings,
                                       do_not_save=True)

        qa.save()

        # status must be auto set as per formula
        self.assertEqual(qa.readings[0].status, "Accepted")
        self.assertEqual(qa.readings[1].status, "Rejected")
        self.assertEqual(qa.readings[2].status, "Accepted")
        self.assertEqual(qa.readings[3].status, "Accepted")

        qa.delete()
        dn.delete()
Пример #20
0
 def test_serial_balance(self):
     item_code = "_Test Stock Report Serial Item"
     # Checks serials which were added through stock in entry.
     columns, data = execute(self.filters)
     self.assertEqual(data[0].in_qty, 2)
     serials_added = get_serial_nos(data[0].serial_no)
     self.assertEqual(len(serials_added), 2)
     # Stock out entry for one of the serials.
     dn = create_delivery_note(item=item_code, serial_no=serials_added[1])
     self.filters.voucher_no = dn.name
     columns, data = execute(self.filters)
     self.assertEqual(data[0].out_qty, -1)
     self.assertEqual(data[0].serial_no, serials_added[1])
     self.assertEqual(data[0].balance_serial_no, serials_added[0])
    def test_intermediate_sr_bin_update(self):
        """Bin should show correct qty even for backdated entries.

		-------------------------------------------
		| creation | Var | Doc  | Qty | balance qty
		-------------------------------------------
		|  1       | SR  | Reco | 10  | 10     (posting date: today+10)
		|  3       | SR2 | Reco | 11  | 11     (posting date: today+11)
		|  2       | DN  | DN   | 5   | 6 <-- assert in BIN  (posting date: today+12)
		"""
        from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note

        frappe.db.rollback()

        # repost will make this test useless, qty should update in realtime without reposts
        frappe.flags.dont_execute_stock_reposts = True

        item_code = make_item().name
        warehouse = "_Test Warehouse - _TC"

        sr = create_stock_reconciliation(item_code=item_code,
                                         warehouse=warehouse,
                                         qty=10,
                                         rate=100,
                                         posting_date=add_days(nowdate(), 10))

        dn = create_delivery_note(item_code=item_code,
                                  warehouse=warehouse,
                                  qty=5,
                                  rate=120,
                                  posting_date=add_days(nowdate(), 12))
        old_bin_qty = frappe.db.get_value("Bin", {
            "item_code": item_code,
            "warehouse": warehouse
        }, "actual_qty")

        sr2 = create_stock_reconciliation(item_code=item_code,
                                          warehouse=warehouse,
                                          qty=11,
                                          rate=100,
                                          posting_date=add_days(nowdate(), 11))
        new_bin_qty = frappe.db.get_value("Bin", {
            "item_code": item_code,
            "warehouse": warehouse
        }, "actual_qty")

        self.assertEqual(old_bin_qty + 1, new_bin_qty)
        frappe.db.rollback()
    def test_backdated_stock_reco_cancellation_future_negative_stock(self):
        """
		Test if a backdated stock reco cancellation that causes future negative stock is blocked.
		-------------------------------------------
		Var | Doc  | Qty | Balance
		-------------------------------------------
		SR  | Reco | 100 | 100     (posting date: today-1) (shouldn't be cancelled after DN)
		DN  | DN   | 100 |   0     (posting date: today)
		"""
        from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note
        from erpnext.stock.stock_ledger import NegativeStockError

        item_code = make_item().name
        warehouse = "_Test Warehouse - _TC"

        sr = create_stock_reconciliation(
            item_code=item_code,
            warehouse=warehouse,
            qty=100,
            rate=100,
            posting_date=add_days(nowdate(), -1),
        )

        dn = create_delivery_note(item_code=item_code,
                                  warehouse=warehouse,
                                  qty=100,
                                  rate=120,
                                  posting_date=nowdate())

        dn_balance = frappe.db.get_value("Stock Ledger Entry", {
            "voucher_no": dn.name,
            "is_cancelled": 0
        }, "qty_after_transaction")
        self.assertEqual(dn_balance, 0)

        # check if cancellation of stock reco is blocked
        self.assertRaises(NegativeStockError, sr.cancel)

        repost_exists = bool(
            frappe.db.exists("Repost Item Valuation", {"voucher_no": sr.name}))
        self.assertFalse(
            repost_exists,
            msg="Negative stock validation not working on reco cancellation")
Пример #23
0
    def test_return_against_sales_order(self):
        so = make_sales_order()

        dn = create_dn_against_so(so.name, 6)

        so.load_from_db()
        self.assertEqual(so.get("items")[0].delivered_qty, 6)

        # Check delivered_qty after make_sales_invoice with update_stock checked
        si2 = make_sales_invoice(so.name)
        si2.set("update_stock", 1)
        si2.get("items")[0].qty = 3
        si2.insert()
        si2.submit()

        so.load_from_db()

        self.assertEqual(so.get("items")[0].delivered_qty, 9)

        # Make return deliver note, sales invoice and check quantity
        from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note
        from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice

        dn1 = create_delivery_note(is_return=1,
                                   return_against=dn.name,
                                   qty=-3,
                                   do_not_submit=True)
        dn1.items[0].against_sales_order = so.name
        dn1.items[0].so_detail = so.items[0].name
        dn1.submit()

        si1 = create_sales_invoice(is_return=1,
                                   return_against=si2.name,
                                   qty=-1,
                                   update_stock=1,
                                   do_not_submit=True)
        si1.items[0].sales_order = so.name
        si1.items[0].so_detail = so.items[0].name
        si1.submit()

        so.load_from_db()
        self.assertEqual(so.get("items")[0].delivered_qty, 5)
Пример #24
0
	def test_serial_numbers_against_delivery_note(self):
		""" 
			check if the sales invoice item serial numbers and the delivery note items
			serial numbers are same
		"""
		from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item
		from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note
		from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice
		from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos

		se = make_serialized_item()
		serial_nos = get_serial_nos(se.get("items")[0].serial_no)

		dn = create_delivery_note(item=se.get("items")[0].item_code, serial_no=serial_nos[0])
		dn.submit()

		si = make_sales_invoice(dn.name)
		si.save()

		self.assertEquals(si.get("items")[0].serial_no, dn.get("items")[0].serial_no)
Пример #25
0
	def test_serial_numbers_against_delivery_note(self):
		""" 
			check if the sales invoice item serial numbers and the delivery note items
			serial numbers are same
		"""
		from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item
		from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note
		from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice
		from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos

		se = make_serialized_item()
		serial_nos = get_serial_nos(se.get("items")[0].serial_no)

		dn = create_delivery_note(item=se.get("items")[0].item_code, serial_no=serial_nos[0])
		dn.submit()

		si = make_sales_invoice(dn.name)
		si.save()

		self.assertEquals(si.get("items")[0].serial_no, dn.get("items")[0].serial_no)
Пример #26
0
    def test_customer_credit_limit(self):
        from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note
        from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
        from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
        from erpnext.selling.doctype.sales_order.sales_order import make_sales_invoice

        outstanding_amt = self.get_customer_outstanding_amount()
        credit_limit = get_credit_limit('_Test Customer', '_Test Company')

        if outstanding_amt <= 0.0:
            item_qty = int((abs(outstanding_amt) + 200) / 100)
            make_sales_order(qty=item_qty)

        if credit_limit == 0.0:
            frappe.db.set_value("Customer", '_Test Customer', 'credit_limit',
                                outstanding_amt - 50.0)

        # Sales Order
        so = make_sales_order(do_not_submit=True)
        self.assertRaises(frappe.ValidationError, so.submit)

        # Delivery Note
        dn = create_delivery_note(do_not_submit=True)
        self.assertRaises(frappe.ValidationError, dn.submit)

        # Sales Invoice
        si = create_sales_invoice(do_not_submit=True)
        self.assertRaises(frappe.ValidationError, si.submit)

        if credit_limit > outstanding_amt:
            frappe.db.set_value("Customer", '_Test Customer', 'credit_limit',
                                credit_limit)

        # Makes Sales invoice from Sales Order
        so.save(ignore_permissions=True)
        si = make_sales_invoice(so.name)
        si.save(ignore_permissions=True)
        self.assertRaises(frappe.ValidationError, make_sales_order)
Пример #27
0
    def test_correct_serial_no_incoming_rate(self):
        """Check correct consumption rate based on serial no record."""
        item_code = "_Test Serialized Item"
        warehouse = "_Test Warehouse - _TC"
        serial_nos = ["LOWVALUATION", "HIGHVALUATION"]

        in1 = make_stock_entry(item_code=item_code,
                               to_warehouse=warehouse,
                               qty=1,
                               rate=42,
                               serial_no=serial_nos[0])
        in2 = make_stock_entry(item_code=item_code,
                               to_warehouse=warehouse,
                               qty=1,
                               rate=113,
                               serial_no=serial_nos[1])

        out = create_delivery_note(item_code=item_code,
                                   qty=1,
                                   serial_no=serial_nos[0],
                                   do_not_submit=True)

        # change serial no
        out.items[0].serial_no = serial_nos[1]
        out.save()
        out.submit()

        value_diff = frappe.db.get_value(
            "Stock Ledger Entry",
            {
                "voucher_no": out.name,
                "voucher_type": "Delivery Note"
            },
            "stock_value_difference",
        )
        self.assertEqual(value_diff, -113)
Пример #28
0
	def test_customer_credit_limit(self):
		from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note
		from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
		from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
		from erpnext.selling.doctype.sales_order.sales_order import make_sales_invoice

		outstanding_amt = self.get_customer_outstanding_amount()
		credit_limit = get_credit_limit('_Test Customer', '_Test Company')

		if outstanding_amt <= 0.0:
			item_qty = int((abs(outstanding_amt) + 200)/100)
			make_sales_order(qty=item_qty)

		if credit_limit == 0.0:
			frappe.db.set_value("Customer", '_Test Customer', 'credit_limit', outstanding_amt - 50.0)

		# Sales Order
		so = make_sales_order(do_not_submit=True)
		self.assertRaises(frappe.ValidationError, so.submit)

		# Delivery Note
		dn = create_delivery_note(do_not_submit=True)
		self.assertRaises(frappe.ValidationError, dn.submit)

		# Sales Invoice
		si = create_sales_invoice(do_not_submit=True)
		self.assertRaises(frappe.ValidationError, si.submit)

		if credit_limit > outstanding_amt:
			frappe.db.set_value("Customer", '_Test Customer', 'credit_limit', credit_limit)

		# Makes Sales invoice from Sales Order
		so.save(ignore_permissions=True)
		si = make_sales_invoice(so.name)
		si.save(ignore_permissions=True)
		self.assertRaises(frappe.ValidationError, make_sales_order)
Пример #29
0
    def test_serialized_lcv_delivered(self):
        """In some cases you'd want to deliver before you can know all the
		landed costs, this should be allowed for serial nos too.

		Case:
		        - receipt a serial no @ X rate
		        - delivery the serial no @ X rate
		        - add LCV to receipt X + Y
		        - LCV should be successful
		        - delivery should reflect X+Y valuation.
		"""
        serial_no = "LCV_TEST_SR_NO"
        item_code = "_Test Serialized Item"
        warehouse = "Stores - TCP1"

        pr = make_purchase_receipt(
            company="_Test Company with perpetual inventory",
            warehouse=warehouse,
            qty=1,
            rate=200,
            item_code=item_code,
            serial_no=serial_no,
        )

        serial_no_rate = frappe.db.get_value("Serial No", serial_no,
                                             "purchase_rate")

        # deliver it before creating LCV
        dn = create_delivery_note(
            item_code=item_code,
            company="_Test Company with perpetual inventory",
            warehouse="Stores - TCP1",
            serial_no=serial_no,
            qty=1,
            rate=500,
            cost_center="Main - TCP1",
            expense_account="Cost of Goods Sold - TCP1",
        )

        charges = 10
        create_landed_cost_voucher("Purchase Receipt",
                                   pr.name,
                                   pr.company,
                                   charges=charges)

        new_purchase_rate = serial_no_rate + charges

        serial_no = frappe.db.get_value("Serial No",
                                        serial_no,
                                        ["warehouse", "purchase_rate"],
                                        as_dict=1)

        self.assertEqual(serial_no.purchase_rate, new_purchase_rate)

        stock_value_difference = frappe.db.get_value(
            "Stock Ledger Entry",
            filters={
                "voucher_no": dn.name,
                "voucher_type": dn.doctype,
                "is_cancelled": 0,  # LCV cancels with same name.
            },
            fieldname="stock_value_difference",
        )

        # reposting should update the purchase rate in future delivery
        self.assertEqual(stock_value_difference, -new_purchase_rate)
Пример #30
0
    def test_inter_company_transfer_intermediate_cancellation(self):
        """
			Receive into and Deliver Serial No from one company.
			Then Receive into and Deliver from second company.
			Try to cancel intermediate receipts/deliveries to test if it is blocked.
		"""
        se = make_serialized_item(target_warehouse="_Test Warehouse - _TC")
        serial_nos = get_serial_nos(se.get("items")[0].serial_no)

        sn_doc = frappe.get_doc("Serial No", serial_nos[0])

        # check Serial No details after purchase in first company
        self.assertEqual(sn_doc.status, "Active")
        self.assertEqual(sn_doc.company, "_Test Company")
        self.assertEqual(sn_doc.warehouse, "_Test Warehouse - _TC")
        self.assertEqual(sn_doc.purchase_document_no, se.name)

        dn = create_delivery_note(
            item_code="_Test Serialized Item With Series",
            qty=1,
            serial_no=serial_nos[0])
        sn_doc.reload()
        # check Serial No details after delivery from **first** company
        self.assertEqual(sn_doc.status, "Delivered")
        self.assertEqual(sn_doc.company, "_Test Company")
        self.assertEqual(sn_doc.warehouse, None)
        self.assertEqual(sn_doc.delivery_document_no, dn.name)

        # try cancelling the first Serial No Receipt, even though it is delivered
        # block cancellation is Serial No is out of the warehouse
        self.assertRaises(frappe.ValidationError, se.cancel)

        # receive serial no in second company
        wh = create_warehouse("_Test Warehouse", company="_Test Company 1")
        pr = make_purchase_receipt(
            item_code="_Test Serialized Item With Series",
            qty=1,
            serial_no=serial_nos[0],
            company="_Test Company 1",
            warehouse=wh)
        sn_doc.reload()

        self.assertEqual(sn_doc.warehouse, wh)
        # try cancelling the delivery from the first company
        # block cancellation as Serial No belongs to different company
        self.assertRaises(frappe.ValidationError, dn.cancel)

        # deliver from second company
        dn_2 = create_delivery_note(
            item_code="_Test Serialized Item With Series",
            qty=1,
            serial_no=serial_nos[0],
            company="_Test Company 1",
            warehouse=wh)
        sn_doc.reload()

        # check Serial No details after delivery from **second** company
        self.assertEqual(sn_doc.status, "Delivered")
        self.assertEqual(sn_doc.company, "_Test Company 1")
        self.assertEqual(sn_doc.warehouse, None)
        self.assertEqual(sn_doc.delivery_document_no, dn_2.name)

        # cannot cancel any intermediate document before last Delivery Note
        self.assertRaises(frappe.ValidationError, se.cancel)
        self.assertRaises(frappe.ValidationError, dn.cancel)
        self.assertRaises(frappe.ValidationError, pr.cancel)
Пример #31
0
    def test_inter_company_transfer_fallback_on_cancel(self):
        """
			Test Serial No state changes on cancellation.
			If Delivery cancelled, it should fall back on last Receipt in the same company.
			If Receipt is cancelled, it should be Inactive in the same company.
		"""
        # Receipt in **first** company
        se = make_serialized_item(target_warehouse="_Test Warehouse - _TC")
        serial_nos = get_serial_nos(se.get("items")[0].serial_no)
        sn_doc = frappe.get_doc("Serial No", serial_nos[0])

        # Delivery from first company
        dn = create_delivery_note(
            item_code="_Test Serialized Item With Series",
            qty=1,
            serial_no=serial_nos[0])

        # Receipt in **second** company
        wh = create_warehouse("_Test Warehouse", company="_Test Company 1")
        pr = make_purchase_receipt(
            item_code="_Test Serialized Item With Series",
            qty=1,
            serial_no=serial_nos[0],
            company="_Test Company 1",
            warehouse=wh)

        # Delivery from second company
        dn_2 = create_delivery_note(
            item_code="_Test Serialized Item With Series",
            qty=1,
            serial_no=serial_nos[0],
            company="_Test Company 1",
            warehouse=wh)
        sn_doc.reload()

        self.assertEqual(sn_doc.status, "Delivered")
        self.assertEqual(sn_doc.company, "_Test Company 1")
        self.assertEqual(sn_doc.delivery_document_no, dn_2.name)

        dn_2.cancel()
        sn_doc.reload()
        # Fallback on Purchase Receipt if Delivery is cancelled
        self.assertEqual(sn_doc.status, "Active")
        self.assertEqual(sn_doc.company, "_Test Company 1")
        self.assertEqual(sn_doc.warehouse, wh)
        self.assertEqual(sn_doc.purchase_document_no, pr.name)

        pr.cancel()
        sn_doc.reload()
        # Inactive in same company if Receipt cancelled
        self.assertEqual(sn_doc.status, "Inactive")
        self.assertEqual(sn_doc.company, "_Test Company 1")
        self.assertEqual(sn_doc.warehouse, None)

        dn.cancel()
        sn_doc.reload()
        # Fallback on Purchase Receipt in FIRST company if
        # Delivery from FIRST company is cancelled
        self.assertEqual(sn_doc.status, "Active")
        self.assertEqual(sn_doc.company, "_Test Company")
        self.assertEqual(sn_doc.warehouse, "_Test Warehouse - _TC")
        self.assertEqual(sn_doc.purchase_document_no, se.name)
Пример #32
0
    def test_reposting_of_sales_return_for_packed_item(self):
        company = "_Test Company"
        packed_item_code = "_Test Item for Reposting"
        bundled_item = "_Test Bundled Item for Reposting"
        create_product_bundle_item(bundled_item, [[packed_item_code, 4]])

        # Purchase Return: Qty = 50, Rate = 100
        pr = make_purchase_receipt(company=company,
                                   posting_date='2020-04-10',
                                   warehouse="Stores - _TC",
                                   item_code=packed_item_code,
                                   qty=50,
                                   rate=100)

        #Delivery Note: Qty = 5, Rate = 150
        dn = create_delivery_note(item_code=bundled_item,
                                  qty=5,
                                  rate=150,
                                  warehouse="Stores - _TC",
                                  company=company,
                                  expense_account="Cost of Goods Sold - _TC",
                                  cost_center="Main - _TC")

        # check outgoing_rate for DN
        outgoing_rate = abs(
            frappe.db.get_value("Stock Ledger Entry", {
                "voucher_type": "Delivery Note",
                "voucher_no": dn.name
            }, "stock_value_difference") / 20)

        self.assertEqual(dn.packed_items[0].incoming_rate, 100)
        self.assertEqual(outgoing_rate, 100)

        # Return Entry: Qty = -2, Rate = 150
        return_dn = create_delivery_note(
            is_return=1,
            return_against=dn.name,
            item_code=bundled_item,
            qty=-2,
            rate=150,
            company=company,
            warehouse="Stores - _TC",
            expense_account="Cost of Goods Sold - _TC",
            cost_center="Main - _TC")

        # check incoming rate for Return entry
        incoming_rate, stock_value_difference = frappe.db.get_value(
            "Stock Ledger Entry", {
                "voucher_type": "Delivery Note",
                "voucher_no": return_dn.name
            }, ["incoming_rate", "stock_value_difference"])

        self.assertEqual(return_dn.packed_items[0].incoming_rate, 100)
        self.assertEqual(incoming_rate, 100)
        self.assertEqual(stock_value_difference, 800)

        #-------------------------------

        # Landed Cost Voucher to update the rate of incoming Purchase Return: Additional cost = 50
        lcv = create_landed_cost_voucher("Purchase Receipt", pr.name,
                                         pr.company)

        # check outgoing_rate for DN after reposting
        outgoing_rate = abs(
            frappe.db.get_value("Stock Ledger Entry", {
                "voucher_type": "Delivery Note",
                "voucher_no": dn.name
            }, "stock_value_difference") / 20)
        self.assertEqual(outgoing_rate, 101)

        dn.reload()
        self.assertEqual(dn.packed_items[0].incoming_rate, 101)

        # check incoming rate for Return entry after reposting
        incoming_rate, stock_value_difference = frappe.db.get_value(
            "Stock Ledger Entry", {
                "voucher_type": "Delivery Note",
                "voucher_no": return_dn.name
            }, ["incoming_rate", "stock_value_difference"])

        self.assertEqual(incoming_rate, 101)
        self.assertEqual(stock_value_difference, 808)

        return_dn.reload()
        self.assertEqual(return_dn.packed_items[0].incoming_rate, 101)

        # Cleanup data
        return_dn.cancel()
        dn.cancel()
        lcv.cancel()
        pr.cancel()
Пример #33
0
	def test_qa_not_submit(self):
		dn = create_delivery_note(item_code="_Test Item with QA", do_not_submit=True)
		qa = create_quality_inspection(reference_type="Delivery Note", reference_name=dn.name, submit = False)
		dn.items[0].quality_inspection = qa.name
		self.assertRaises(QualityInspectionNotSubmittedError, dn.submit)