Example #1
0
    def test_alternative_item_for_production_rm(self):
        create_stock_reconciliation(item_code='Alternate Item For A RW 1',
                                    warehouse='_Test Warehouse - _TC',
                                    qty=5,
                                    rate=2000)
        create_stock_reconciliation(item_code='Test FG A RW 2',
                                    warehouse='_Test Warehouse - _TC',
                                    qty=5,
                                    rate=2000)
        pro_order = make_wo_order_test_record(
            production_item='Test Finished Goods - A',
            qty=5,
            source_warehouse='_Test Warehouse - _TC',
            wip_warehouse='Test Supplier Warehouse - _TC')

        reserved_qty_for_production = frappe.db.get_value(
            'Bin', {
                'item_code': 'Test FG A RW 1',
                'warehouse': '_Test Warehouse - _TC'
            }, 'reserved_qty_for_production')

        ste = frappe.get_doc(
            make_stock_entry(pro_order.name,
                             "Material Transfer for Manufacture", 5))
        ste.insert()

        for item in ste.items:
            if item.item_code == 'Test FG A RW 1':
                item.item_code = 'Alternate Item For A RW 1'
                item.item_name = 'Alternate Item For A RW 1'
                item.description = 'Alternate Item For A RW 1'
                item.original_item = 'Test FG A RW 1'

        ste.submit()
        reserved_qty_for_production_after_transfer = frappe.db.get_value(
            'Bin', {
                'item_code': 'Test FG A RW 1',
                'warehouse': '_Test Warehouse - _TC'
            }, 'reserved_qty_for_production')

        self.assertEqual(reserved_qty_for_production_after_transfer,
                         flt(reserved_qty_for_production - 5))
        ste1 = frappe.get_doc(
            make_stock_entry(pro_order.name, "Manufacture", 5))

        status = False
        for d in ste1.items:
            if d.item_code == 'Alternate Item For A RW 1':
                status = True

        self.assertEqual(status, True)
        ste1.submit()
Example #2
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)
Example #3
0
    def test_production_plan_for_existing_ordered_qty(self):
        sr1 = create_stock_reconciliation(item_code="Raw Material Item 1",
                                          target="_Test Warehouse - _TC",
                                          qty=1,
                                          rate=110)
        sr2 = create_stock_reconciliation(item_code="Raw Material Item 2",
                                          target="_Test Warehouse - _TC",
                                          qty=1,
                                          rate=120)

        pln = create_production_plan(item_code='Test Production Item 1',
                                     ignore_existing_ordered_qty=0)
        self.assertTrue(len(pln.mr_items), 1)
        self.assertTrue(flt(pln.mr_items[0].quantity), 1.0)

        sr1.cancel()
        sr2.cancel()
        pln.cancel()
Example #4
0
    def test_production_plan_without_multi_level_for_existing_ordered_qty(
            self):
        sr1 = create_stock_reconciliation(item_code="Raw Material Item 1",
                                          target="_Test Warehouse - _TC",
                                          qty=1,
                                          rate=130)
        sr2 = create_stock_reconciliation(item_code="Subassembly Item 1",
                                          target="_Test Warehouse - _TC",
                                          qty=1,
                                          rate=140)

        pln = create_production_plan(item_code='Test Production Item 1',
                                     use_multi_level_bom=0,
                                     ignore_existing_ordered_qty=0)
        self.assertTrue(len(pln.mr_items), 0)

        sr1.cancel()
        sr2.cancel()
        pln.cancel()
Example #5
0
    def _test_auto_material_request(self,
                                    item_code,
                                    material_request_type="Purchase",
                                    warehouse="_Test Warehouse - _TC"):
        variant = frappe.get_doc("Item", item_code)

        projected_qty, actual_qty = frappe.db.get_value(
            "Bin", {
                "item_code": item_code,
                "warehouse": warehouse
            }, ["projected_qty", "actual_qty"]) or [0, 0]

        # stock entry reqd for auto-reorder
        create_stock_reconciliation(item_code=item_code,
                                    warehouse=warehouse,
                                    qty=actual_qty + abs(projected_qty) + 10,
                                    rate=100)

        projected_qty = frappe.db.get_value("Bin", {
            "item_code": item_code,
            "warehouse": warehouse
        }, "projected_qty") or 0

        frappe.db.set_value("Stock Settings", None, "auto_indent", 1)

        # update re-level qty so that it is more than projected_qty
        if projected_qty >= variant.reorder_levels[0].warehouse_reorder_level:
            variant.reorder_levels[0].warehouse_reorder_level += projected_qty
            variant.reorder_levels[
                0].material_request_type = material_request_type
            variant.save()

        from erpbee.stock.reorder_item import reorder_item
        mr_list = reorder_item()

        frappe.db.set_value("Stock Settings", None, "auto_indent", 0)

        items = []
        for mr in mr_list:
            for d in mr.items:
                items.append(d.item_code)

        self.assertTrue(item_code in items)
Example #6
0
def reset_item_valuation_rate(item_code,
                              warehouse_list=None,
                              qty=None,
                              rate=None):
    if warehouse_list and isinstance(warehouse_list, string_types):
        warehouse_list = [warehouse_list]

    if not warehouse_list:
        warehouse_list = frappe.db.sql_list(
            """
			select warehouse from `tabBin`
			where item_code=%s and actual_qty > 0
		""", item_code)

        if not warehouse_list:
            warehouse_list.append("_Test Warehouse - _TC")

    for warehouse in warehouse_list:
        create_stock_reconciliation(item_code=item_code,
                                    warehouse=warehouse,
                                    qty=qty,
                                    rate=rate)
Example #7
0
def make_items():
    items = [
        'Test Finished Goods - A', 'Test FG A RW 1', 'Test FG A RW 2',
        'Alternate Item For A RW 1'
    ]
    for item_code in items:
        if not frappe.db.exists('Item', item_code):
            create_item(item_code)

    create_stock_reconciliation(item_code="Test FG A RW 1",
                                warehouse='_Test Warehouse - _TC',
                                qty=10,
                                rate=2000)

    if frappe.db.exists('Item', 'Test FG A RW 1'):
        doc = frappe.get_doc('Item', 'Test FG A RW 1')
        doc.allow_alternative_item = 1
        doc.save()

    if frappe.db.exists('Item', 'Test Finished Goods - A'):
        doc = frappe.get_doc('Item', 'Test Finished Goods - A')
        doc.is_sub_contracted_item = 1
        doc.save()

    if not frappe.db.get_value('BOM', {
            'item': 'Test Finished Goods - A',
            'docstatus': 1
    }):
        make_bom(item='Test Finished Goods - A',
                 raw_materials=['Test FG A RW 1', 'Test FG A RW 2'])

    if not frappe.db.get_value('Warehouse',
                               {'warehouse_name': 'Test Supplier Warehouse'}):
        frappe.get_doc({
            'doctype': 'Warehouse',
            'warehouse_name': 'Test Supplier Warehouse',
            'company': '_Test Company'
        }).insert(ignore_permissions=True)
Example #8
0
    def test_item_cost_reposting(self):
        company = "_Test Company"

        # _Test Item for Reposting at Stores warehouse on 10-04-2020: Qty = 50, Rate = 100
        create_stock_reconciliation(item_code="_Test Item for Reposting",
                                    warehouse="Stores - _TC",
                                    qty=50,
                                    rate=100,
                                    company=company,
                                    expense_account="Stock Adjustment - _TC",
                                    posting_date='2020-04-10',
                                    posting_time='14:00')

        # _Test Item for Reposting at FG warehouse on 20-04-2020: Qty = 10, Rate = 200
        create_stock_reconciliation(item_code="_Test Item for Reposting",
                                    warehouse="Finished Goods - _TC",
                                    qty=10,
                                    rate=200,
                                    company=company,
                                    expense_account="Stock Adjustment - _TC",
                                    posting_date='2020-04-20',
                                    posting_time='14:00')

        # _Test Item for Reposting transferred from Stores to FG warehouse on 30-04-2020
        make_stock_entry(item_code="_Test Item for Reposting",
                         source="Stores - _TC",
                         target="Finished Goods - _TC",
                         company=company,
                         qty=10,
                         expense_account="Stock Adjustment - _TC",
                         posting_date='2020-04-30',
                         posting_time='14:00')
        target_wh_sle = get_previous_sle({
            "item_code": "_Test Item for Reposting",
            "warehouse": "Finished Goods - _TC",
            "posting_date": '2020-04-30',
            "posting_time": '14:00'
        })

        self.assertEqual(target_wh_sle.get("valuation_rate"), 150)

        # Repack entry on 5-5-2020
        repack = create_repack_entry(company=company,
                                     posting_date='2020-05-05',
                                     posting_time='14:00')

        finished_item_sle = get_previous_sle({
            "item_code": "_Test Finished Item for Reposting",
            "warehouse": "Finished Goods - _TC",
            "posting_date": '2020-05-05',
            "posting_time": '14:00'
        })
        self.assertEqual(finished_item_sle.get("incoming_rate"), 540)
        self.assertEqual(finished_item_sle.get("valuation_rate"), 540)

        # Reconciliation for _Test Item for Reposting at Stores on 12-04-2020: Qty = 50, Rate = 150
        create_stock_reconciliation(item_code="_Test Item for Reposting",
                                    warehouse="Stores - _TC",
                                    qty=50,
                                    rate=150,
                                    company=company,
                                    expense_account="Stock Adjustment - _TC",
                                    posting_date='2020-04-12',
                                    posting_time='14:00')

        # Check valuation rate of finished goods warehouse after back-dated entry at Stores
        target_wh_sle = get_previous_sle({
            "item_code": "_Test Item for Reposting",
            "warehouse": "Finished Goods - _TC",
            "posting_date": '2020-04-30',
            "posting_time": '14:00'
        })
        self.assertEqual(target_wh_sle.get("incoming_rate"), 150)
        self.assertEqual(target_wh_sle.get("valuation_rate"), 175)

        # Check valuation rate of repacked item after back-dated entry at Stores
        finished_item_sle = get_previous_sle({
            "item_code": "_Test Finished Item for Reposting",
            "warehouse": "Finished Goods - _TC",
            "posting_date": '2020-05-05',
            "posting_time": '14:00'
        })
        self.assertEqual(finished_item_sle.get("incoming_rate"), 790)
        self.assertEqual(finished_item_sle.get("valuation_rate"), 790)

        # Check updated rate in Repack entry
        repack.reload()
        self.assertEqual(repack.items[0].get("basic_rate"), 150)
        self.assertEqual(repack.items[1].get("basic_rate"), 750)
Example #9
0
    def test_delivery_of_bundled_items_to_target_warehouse(self):
        company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company')

        set_valuation_method("_Test Item", "FIFO")
        set_valuation_method("_Test Item Home Desktop 100", "FIFO")

        target_warehouse = get_warehouse(
            company=company,
            abbr="TCP1",
            warehouse_name="_Test Customer Warehouse").name

        for warehouse in ("Stores - TCP1", target_warehouse):
            create_stock_reconciliation(
                item_code="_Test Item",
                warehouse=warehouse,
                company=company,
                expense_account="Stock Adjustment - TCP1",
                qty=500,
                rate=100)
            create_stock_reconciliation(
                item_code="_Test Item Home Desktop 100",
                company=company,
                expense_account="Stock Adjustment - TCP1",
                warehouse=warehouse,
                qty=500,
                rate=100)

        dn = create_delivery_note(
            item_code="_Test Product Bundle Item",
            company='_Test Company with perpetual inventory',
            cost_center='Main - TCP1',
            expense_account="Cost of Goods Sold - TCP1",
            do_not_submit=True,
            qty=5,
            rate=500,
            warehouse="Stores - TCP1",
            target_warehouse=target_warehouse)

        dn.submit()

        # qty after delivery
        actual_qty_at_source = get_qty_after_transaction(
            warehouse="Stores - TCP1")
        self.assertEqual(actual_qty_at_source, 475)

        actual_qty_at_target = get_qty_after_transaction(
            warehouse=target_warehouse)
        self.assertEqual(actual_qty_at_target, 525)

        # stock value diff for source warehouse for "_Test Item"
        stock_value_difference = frappe.db.get_value(
            "Stock Ledger Entry", {
                "voucher_type": "Delivery Note",
                "voucher_no": dn.name,
                "item_code": "_Test Item",
                "warehouse": "Stores - TCP1"
            }, "stock_value_difference")

        # stock value diff for target warehouse
        stock_value_difference1 = frappe.db.get_value(
            "Stock Ledger Entry", {
                "voucher_type": "Delivery Note",
                "voucher_no": dn.name,
                "item_code": "_Test Item",
                "warehouse": target_warehouse
            }, "stock_value_difference")

        self.assertEqual(abs(stock_value_difference), stock_value_difference1)

        # Check gl entries
        gl_entries = get_gl_entries("Delivery Note", dn.name)
        self.assertTrue(gl_entries)

        stock_value_difference = abs(
            frappe.db.sql(
                """select sum(stock_value_difference)
			from `tabStock Ledger Entry` where voucher_type='Delivery Note' and voucher_no=%s
			and warehouse='Stores - TCP1'""", dn.name)[0][0])

        expected_values = {
            "Stock In Hand - TCP1": [0.0, stock_value_difference],
            target_warehouse: [stock_value_difference, 0.0]
        }
        for i, gle in enumerate(gl_entries):
            self.assertEqual([gle.debit, gle.credit],
                             expected_values.get(gle.account))
Example #10
0
    def test_return_entire_bundled_items(self):
        company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company')

        create_stock_reconciliation(item_code="_Test Item",
                                    warehouse="Stores - TCP1",
                                    qty=50,
                                    rate=100,
                                    company=company,
                                    expense_account="Stock Adjustment - TCP1")
        create_stock_reconciliation(item_code="_Test Item Home Desktop 100",
                                    warehouse="Stores - TCP1",
                                    qty=50,
                                    rate=100,
                                    company=company,
                                    expense_account="Stock Adjustment - TCP1")

        actual_qty = get_qty_after_transaction(warehouse="Stores - TCP1")
        self.assertEqual(actual_qty, 50)

        dn = create_delivery_note(item_code="_Test Product Bundle Item",
                                  qty=5,
                                  rate=500,
                                  company=company,
                                  warehouse="Stores - TCP1",
                                  expense_account="Cost of Goods Sold - TCP1",
                                  cost_center="Main - TCP1")

        # qty after return
        actual_qty = get_qty_after_transaction(warehouse="Stores - TCP1")
        self.assertEqual(actual_qty, 25)

        #  return bundled item
        dn1 = create_delivery_note(item_code='_Test Product Bundle Item',
                                   is_return=1,
                                   return_against=dn.name,
                                   qty=-2,
                                   rate=500,
                                   company=company,
                                   warehouse="Stores - TCP1",
                                   expense_account="Cost of Goods Sold - TCP1",
                                   cost_center="Main - TCP1")

        # qty after return
        actual_qty = get_qty_after_transaction(warehouse="Stores - TCP1")
        self.assertEqual(actual_qty, 35)

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

        self.assertEqual(incoming_rate, 100)
        stock_in_hand_account = get_inventory_account('_Test Company',
                                                      dn1.items[0].warehouse)

        # Check gl entry for warehouse
        gle_warehouse_amount = frappe.db.get_value(
            "GL Entry", {
                "voucher_type": "Delivery Note",
                "voucher_no": dn1.name,
                "account": stock_in_hand_account
            }, "debit")

        self.assertEqual(gle_warehouse_amount, 1400)
Example #11
0
    def test_return_single_item_from_bundled_items(self):
        company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company')

        create_stock_reconciliation(item_code="_Test Item",
                                    warehouse="Stores - TCP1",
                                    qty=50,
                                    rate=100,
                                    company=company,
                                    expense_account="Stock Adjustment - TCP1")
        create_stock_reconciliation(item_code="_Test Item Home Desktop 100",
                                    warehouse="Stores - TCP1",
                                    qty=50,
                                    rate=100,
                                    company=company,
                                    expense_account="Stock Adjustment - TCP1")

        dn = create_delivery_note(item_code="_Test Product Bundle Item",
                                  qty=5,
                                  rate=500,
                                  company=company,
                                  warehouse="Stores - TCP1",
                                  expense_account="Cost of Goods Sold - TCP1",
                                  cost_center="Main - TCP1")

        # Qty after delivery
        actual_qty_1 = get_qty_after_transaction(warehouse="Stores - TCP1")
        self.assertEqual(actual_qty_1, 25)

        # outgoing_rate
        outgoing_rate = frappe.db.get_value(
            "Stock Ledger Entry", {
                "voucher_type": "Delivery Note",
                "voucher_no": dn.name,
                "item_code": "_Test Item"
            }, "stock_value_difference") / 25

        # return 'test item' from packed items
        dn1 = create_delivery_note(is_return=1,
                                   return_against=dn.name,
                                   qty=-10,
                                   rate=500,
                                   company=company,
                                   warehouse="Stores - TCP1",
                                   expense_account="Cost of Goods Sold - TCP1",
                                   cost_center="Main - TCP1")

        # qty after return
        actual_qty_2 = get_qty_after_transaction(warehouse="Stores - TCP1")
        self.assertEqual(actual_qty_2, 35)

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

        self.assertEqual(flt(incoming_rate, 3), abs(flt(outgoing_rate, 3)))
        stock_in_hand_account = get_inventory_account(company,
                                                      dn1.items[0].warehouse)

        # Check gl entry for warehouse
        gle_warehouse_amount = frappe.db.get_value(
            "GL Entry", {
                "voucher_type": "Delivery Note",
                "voucher_no": dn1.name,
                "account": stock_in_hand_account
            }, "debit")

        self.assertEqual(gle_warehouse_amount, stock_value_difference)
Example #12
0
    def test_alternative_item_for_subcontract_rm(self):
        create_stock_reconciliation(item_code='Alternate Item For A RW 1',
                                    warehouse='_Test Warehouse - _TC',
                                    qty=5,
                                    rate=2000)
        create_stock_reconciliation(item_code='Test FG A RW 2',
                                    warehouse='_Test Warehouse - _TC',
                                    qty=5,
                                    rate=2000)

        supplier_warehouse = "Test Supplier Warehouse - _TC"
        po = create_purchase_order(item="Test Finished Goods - A",
                                   is_subcontracted='Yes',
                                   qty=5,
                                   rate=3000,
                                   supplier_warehouse=supplier_warehouse)

        rm_item = [{
            "item_code": "Test Finished Goods - A",
            "rm_item_code": "Test FG A RW 1",
            "item_name": "Test FG A RW 1",
            "qty": 5,
            "warehouse": "_Test Warehouse - _TC",
            "rate": 2000,
            "amount": 10000,
            "stock_uom": "Nos"
        }, {
            "item_code": "Test Finished Goods - A",
            "rm_item_code": "Test FG A RW 2",
            "item_name": "Test FG A RW 2",
            "qty": 5,
            "warehouse": "_Test Warehouse - _TC",
            "rate": 2000,
            "amount": 10000,
            "stock_uom": "Nos"
        }]

        rm_item_string = json.dumps(rm_item)
        reserved_qty_for_sub_contract = frappe.db.get_value(
            'Bin', {
                'item_code': 'Test FG A RW 1',
                'warehouse': '_Test Warehouse - _TC'
            }, 'reserved_qty_for_sub_contract')

        se = frappe.get_doc(make_rm_stock_entry(po.name, rm_item_string))
        se.to_warehouse = supplier_warehouse
        se.insert()

        doc = frappe.get_doc('Stock Entry', se.name)
        for item in doc.items:
            if item.item_code == 'Test FG A RW 1':
                item.item_code = 'Alternate Item For A RW 1'
                item.item_name = 'Alternate Item For A RW 1'
                item.description = 'Alternate Item For A RW 1'
                item.original_item = 'Test FG A RW 1'

        doc.save()
        doc.submit()
        after_transfer_reserved_qty_for_sub_contract = frappe.db.get_value(
            'Bin', {
                'item_code': 'Test FG A RW 1',
                'warehouse': '_Test Warehouse - _TC'
            }, 'reserved_qty_for_sub_contract')

        self.assertEqual(after_transfer_reserved_qty_for_sub_contract,
                         flt(reserved_qty_for_sub_contract - 5))

        pr = make_purchase_receipt(po.name)
        pr.save()

        pr = frappe.get_doc('Purchase Receipt', pr.name)
        status = False
        for d in pr.supplied_items:
            if d.rm_item_code == 'Alternate Item For A RW 1':
                status = True

        self.assertEqual(status, True)