diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.py b/erpnext/accounts/doctype/gl_entry/gl_entry.py index b7266825d0..bbdf17ebdf 100644 --- a/erpnext/accounts/doctype/gl_entry/gl_entry.py +++ b/erpnext/accounts/doctype/gl_entry/gl_entry.py @@ -9,7 +9,7 @@ from frappe import _ from frappe.model.document import Document -class GlEntry(Document): +class GLEntry(Document): def validate(self): self.check_mandatory() diff --git a/erpnext/accounts/doctype/journal_voucher/journal_voucher.py b/erpnext/accounts/doctype/journal_voucher/journal_voucher.py index 9829a17954..0ba0208ecf 100644 --- a/erpnext/accounts/doctype/journal_voucher/journal_voucher.py +++ b/erpnext/accounts/doctype/journal_voucher/journal_voucher.py @@ -353,13 +353,13 @@ def get_payment_entry_from_sales_invoice(sales_invoice): jv.remark = 'Payment received against Sales Invoice {0}. {1}'.format(si.name, si.remarks) # credit customer - jv.doclist[1].account = si.debit_to - jv.doclist[1].balance = get_balance_on(si.debit_to) - jv.doclist[1].credit = si.outstanding_amount - jv.doclist[1].against_invoice = si.name + jv.get("entries")[0].account = si.debit_to + jv.get("entries")[0].balance = get_balance_on(si.debit_to) + jv.get("entries")[0].credit = si.outstanding_amount + jv.get("entries")[0].against_invoice = si.name # debit bank - jv.doclist[2].debit = si.outstanding_amount + jv.get("entries")[1].debit = si.outstanding_amount return jv.as_dict() @@ -371,13 +371,13 @@ def get_payment_entry_from_purchase_invoice(purchase_invoice): jv.remark = 'Payment against Purchase Invoice {0}. {1}'.format(pi.name, pi.remarks) # credit supplier - jv.doclist[1].account = pi.credit_to - jv.doclist[1].balance = get_balance_on(pi.credit_to) - jv.doclist[1].debit = pi.outstanding_amount - jv.doclist[1].against_voucher = pi.name + jv.get("entries")[0].account = pi.credit_to + jv.get("entries")[0].balance = get_balance_on(pi.credit_to) + jv.get("entries")[0].debit = pi.outstanding_amount + jv.get("entries")[0].against_voucher = pi.name # credit bank - jv.doclist[2].credit = pi.outstanding_amount + jv.get("entries")[1].credit = pi.outstanding_amount return jv.as_dict() diff --git a/erpnext/accounts/doctype/journal_voucher/test_journal_voucher.py b/erpnext/accounts/doctype/journal_voucher/test_journal_voucher.py index c3a3d85ae9..962d9a09db 100644 --- a/erpnext/accounts/doctype/journal_voucher/test_journal_voucher.py +++ b/erpnext/accounts/doctype/journal_voucher/test_journal_voucher.py @@ -9,7 +9,7 @@ import frappe class TestJournalVoucher(unittest.TestCase): def test_journal_voucher_with_against_jv(self): self.clear_account_balance() - jv_invoice = frappe.copy_doc(test_records[2]) + jv_invoice = frappe.copy_doc(test_records[1]) jv_invoice.insert() jv_invoice.submit() @@ -17,7 +17,7 @@ class TestJournalVoucher(unittest.TestCase): where against_jv=%s""", jv_invoice.name)) jv_payment = frappe.copy_doc(test_records[0]) - jv_payment.doclist[1].against_jv = jv_invoice.name + jv_payment.get("entries")[0].against_jv = jv_invoice.name jv_payment.insert() jv_payment.submit() @@ -38,7 +38,7 @@ class TestJournalVoucher(unittest.TestCase): set_perpetual_inventory() jv = frappe.copy_doc(test_records[0]) - jv.doclist[1].account = "_Test Warehouse - _TC" + jv.get("entries")[0].account = "_Test Warehouse - _TC" jv.insert() from erpnext.accounts.general_ledger import StockAccountInvalidTransaction @@ -51,10 +51,10 @@ class TestJournalVoucher(unittest.TestCase): self.clear_account_balance() jv = frappe.copy_doc(test_records[0]) - jv.doclist[2].account = "_Test Account Cost for Goods Sold - _TC" - jv.doclist[2].cost_center = "_Test Cost Center - _TC" - jv.doclist[2].debit = 20000.0 - jv.doclist[1].credit = 20000.0 + jv.get("entries")[1].account = "_Test Account Cost for Goods Sold - _TC" + jv.get("entries")[1].cost_center = "_Test Cost Center - _TC" + jv.get("entries")[1].debit = 20000.0 + jv.get("entries")[0].credit = 20000.0 jv.insert() jv.submit() self.assertTrue(frappe.db.get_value("GL Entry", @@ -66,10 +66,10 @@ class TestJournalVoucher(unittest.TestCase): self.clear_account_balance() jv = frappe.copy_doc(test_records[0]) - jv.doclist[2].account = "_Test Account Cost for Goods Sold - _TC" - jv.doclist[2].cost_center = "_Test Cost Center - _TC" - jv.doclist[2].debit = 20000.0 - jv.doclist[1].credit = 20000.0 + jv.get("entries")[1].account = "_Test Account Cost for Goods Sold - _TC" + jv.get("entries")[1].cost_center = "_Test Cost Center - _TC" + jv.get("entries")[1].debit = 20000.0 + jv.get("entries")[0].credit = 20000.0 jv.insert() self.assertRaises(BudgetError, jv.submit) @@ -85,10 +85,10 @@ class TestJournalVoucher(unittest.TestCase): jv = frappe.copy_doc(test_records[0]) jv.posting_date = "2013-08-12" - jv.doclist[2].account = "_Test Account Cost for Goods Sold - _TC" - jv.doclist[2].cost_center = "_Test Cost Center - _TC" - jv.doclist[2].debit = 150000.0 - jv.doclist[1].credit = 150000.0 + jv.get("entries")[1].account = "_Test Account Cost for Goods Sold - _TC" + jv.get("entries")[1].cost_center = "_Test Cost Center - _TC" + jv.get("entries")[1].debit = 150000.0 + jv.get("entries")[0].credit = 150000.0 jv.insert() self.assertRaises(BudgetError, jv.submit) @@ -101,20 +101,20 @@ class TestJournalVoucher(unittest.TestCase): self.clear_account_balance() jv = frappe.copy_doc(test_records[0]) - jv.doclist[1].account = "_Test Account Cost for Goods Sold - _TC" - jv.doclist[1].cost_center = "_Test Cost Center - _TC" - jv.doclist[1].credit = 30000.0 - jv.doclist[2].debit = 30000.0 + jv.get("entries")[0].account = "_Test Account Cost for Goods Sold - _TC" + jv.get("entries")[0].cost_center = "_Test Cost Center - _TC" + jv.get("entries")[0].credit = 30000.0 + jv.get("entries")[1].debit = 30000.0 jv.submit() self.assertTrue(frappe.db.get_value("GL Entry", {"voucher_type": "Journal Voucher", "voucher_no": jv.name})) jv1 = frappe.copy_doc(test_records[0]) - jv1.doclist[2].account = "_Test Account Cost for Goods Sold - _TC" - jv1.doclist[2].cost_center = "_Test Cost Center - _TC" - jv1.doclist[2].debit = 40000.0 - jv1.doclist[1].credit = 40000.0 + jv1.get("entries")[1].account = "_Test Account Cost for Goods Sold - _TC" + jv1.get("entries")[1].cost_center = "_Test Cost Center - _TC" + jv1.get("entries")[1].debit = 40000.0 + jv1.get("entries")[0].credit = 40000.0 jv1.submit() self.assertTrue(frappe.db.get_value("GL Entry", diff --git a/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py b/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py index 12facd8aa3..ad58efc869 100644 --- a/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py +++ b/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py @@ -17,9 +17,9 @@ class TestPeriodClosingVoucher(unittest.TestCase): jv.submit() jv1 = frappe.copy_doc(jv_records[0]) - jv1.doclist[2].account = "_Test Account Cost for Goods Sold - _TC" - jv1.doclist[2].debit = 600.0 - jv1.doclist[1].credit = 600.0 + jv1.get("entries")[1].account = "_Test Account Cost for Goods Sold - _TC" + jv1.get("entries")[1].debit = 600.0 + jv1.get("entries")[0].credit = 600.0 jv1.insert() jv1.submit() diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index cb5cd31c5d..885ef4690a 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -23,7 +23,7 @@ class TestPurchaseInvoice(unittest.TestCase): wrapper.insert() wrapper.submit() wrapper.load_from_db() - dl = wrapper.doclist + dl = wrapper expected_gl_entries = { "_Test Supplier - _TC": [0, 1512.30], @@ -37,7 +37,7 @@ class TestPurchaseInvoice(unittest.TestCase): "_Test Account Discount - _TC": [0, 168.03], } gl_entries = frappe.db.sql("""select account, debit, credit from `tabGL Entry` - where voucher_type = 'Purchase Invoice' and voucher_no = %s""", dl[0].name, as_dict=1) + where voucher_type = 'Purchase Invoice' and voucher_no = %s""", dl.name, as_dict=1) for d in gl_entries: self.assertEqual([d.debit, d.credit], expected_gl_entries.get(d.account)) @@ -74,10 +74,10 @@ class TestPurchaseInvoice(unittest.TestCase): self.assertEqual(cint(frappe.defaults.get_global_default("auto_accounting_for_stock")), 1) pi = frappe.copy_doc(test_records[1]) - pi.doclist[1].item_code = "_Test Non Stock Item" - pi.doclist[1].expense_account = "_Test Account Cost for Goods Sold - _TC" - pi.doclist.pop(2) - pi.doclist.pop(3) + pi.get("entries")[0].item_code = "_Test Non Stock Item" + pi.get("entries")[0].expense_account = "_Test Account Cost for Goods Sold - _TC" + pi.get("entries").pop(2) + pi.get("entries").pop(1) pi.insert() pi.submit() @@ -112,7 +112,7 @@ class TestPurchaseInvoice(unittest.TestCase): self.assertEqual(item.item_tax_amount, expected_values[i][1]) self.assertEqual(item.valuation_rate, expected_values[i][2]) - self.assertEqual(wrapper.doclist[0].net_total, 1250) + self.assertEqual(wrapper.net_total, 1250) # tax amounts expected_values = [ @@ -133,7 +133,7 @@ class TestPurchaseInvoice(unittest.TestCase): def test_purchase_invoice_with_subcontracted_item(self): wrapper = frappe.copy_doc(test_records[0]) - wrapper.doclist[1].item_code = "_Test FG Item" + wrapper.get("entries")[0].item_code = "_Test FG Item" wrapper.insert() wrapper.load_from_db() @@ -146,7 +146,7 @@ class TestPurchaseInvoice(unittest.TestCase): self.assertEqual(item.item_tax_amount, expected_values[i][1]) self.assertEqual(item.valuation_rate, expected_values[i][2]) - self.assertEqual(wrapper.doclist[0].net_total, 1250) + self.assertEqual(wrapper.net_total, 1250) # tax amounts expected_values = [ @@ -176,7 +176,7 @@ class TestPurchaseInvoice(unittest.TestCase): pi = frappe.copy_doc(test_records[0]) pi.append("advance_allocation_details", { "journal_voucher": jv.name, - "jv_detail_no": jv.doclist[1].name, + "jv_detail_no": jv.get("entries")[0].name, "advance_amount": 400, "allocated_amount": 300, "remarks": jv.remark diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index ba34b49154..41be553710 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -202,7 +202,7 @@ class SalesInvoice(SellingController): self.terms = frappe.db.get_value("Terms and Conditions", self.tc_name, "terms") # fetch charges - if self.charge and not len(self.get("other_charges")): + if self.taxes_and_charges and not len(self.get("other_charges")): self.set_taxes("other_charges", "taxes_and_charges") def get_advances(self): diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 75a9ab53e6..8baeb76d99 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -20,7 +20,7 @@ class TestSalesInvoice(unittest.TestCase): w.docstatus = '0' w.insert() - w2 = [d for d in w.doclist] + w2 = frappe.copy_doc(test_records[0]) w.submit() w = frappe.get_doc(w2) @@ -89,10 +89,10 @@ class TestSalesInvoice(unittest.TestCase): si = frappe.copy_doc(test_records[2]) si.currency = "USD" si.conversion_rate = 50 - si.doclist[1].rate = 1 - si.doclist[1].price_list_rate = 1 - si.doclist[2].rate = 3 - si.doclist[2].price_list_rate = 3 + si.get("entries")[0].rate = 1 + si.get("entries")[0].price_list_rate = 1 + si.get("entries")[1].rate = 3 + si.get("entries")[1].price_list_rate = 3 si.insert() expected_values = { @@ -243,16 +243,16 @@ class TestSalesInvoice(unittest.TestCase): for i, tax in enumerate(si.get("other_charges")): tax.idx = i+1 - si.doclist[1].price_list_rate = 62.5 - si.doclist[1].price_list_rate = 191 - for i in [3, 5, 6, 7, 8, 9]: - si.doclist[i].included_in_print_rate = 1 + si.get("entries")[0].price_list_rate = 62.5 + si.get("entries")[0].price_list_rate = 191 + for i in [2, 4, 5, 6, 7, 8]: + si.get("other_charges")[i].included_in_print_rate = 1 # tax type "Actual" cannot be inclusive self.assertRaises(frappe.ValidationError, si.insert) # taxes above included type 'On Previous Row Total' should also be included - si.doclist[3].included_in_print_rate = 0 + si.get("other_charges")[0].included_in_print_rate = 0 self.assertRaises(frappe.ValidationError, si.insert) def test_sales_invoice_calculation_base_currency_with_tax_inclusive_price(self): @@ -305,11 +305,11 @@ class TestSalesInvoice(unittest.TestCase): si = frappe.copy_doc(test_records[3]) si.currency = "USD" si.conversion_rate = 50 - si.doclist[1].price_list_rate = 55.56 - si.doclist[1].discount_percentage = 10 - si.doclist[2].price_list_rate = 187.5 - si.doclist[2].discount_percentage = 20 - si.doclist[9].rate = 5000 + si.get("entries")[0].price_list_rate = 55.56 + si.get("entries")[0].discount_percentage = 10 + si.get("entries")[1].price_list_rate = 187.5 + si.get("entries")[1].discount_percentage = 20 + si.get("other_charges")[5].rate = 5000 si.insert() @@ -365,7 +365,7 @@ class TestSalesInvoice(unittest.TestCase): import test_records as jv_test_records jv = frappe.get_doc(frappe.copy_doc(jv_test_records[0])) - jv.doclist[1].against_invoice = w.name + jv.get("entries")[0].against_invoice = w.name jv.insert() jv.submit() @@ -381,7 +381,7 @@ class TestSalesInvoice(unittest.TestCase): tlb.submit() si = frappe.get_doc(frappe.copy_doc(test_records[0])) - si.doclist[1].time_log_batch = "_T-Time Log Batch-00001" + si.get("entries")[0].time_log_batch = "_T-Time Log Batch-00001" si.insert() si.submit() @@ -501,16 +501,16 @@ class TestSalesInvoice(unittest.TestCase): as pr_test_records pr = frappe.copy_doc(pr_test_records[0]) pr.naming_series = "_T-Purchase Receipt-" - pr.doclist[1].warehouse = "_Test Warehouse No Account - _TC" + pr.get("entries")[0].warehouse = "_Test Warehouse No Account - _TC" pr.insert() pr.submit() - si_doclist = frappe.copy_doc(test_records[1]) - si_doclist[0]["update_stock"] = 1 - si_doclist[0]["posting_time"] = "12:05" - si_doclist[1]["warehouse"] = "_Test Warehouse No Account - _TC" + si_doc = frappe.copy_doc(test_records[1]) + si_doc["update_stock"] = 1 + si_doc["posting_time"] = "12:05" + si_doc.get("entries")["warehouse"] = "_Test Warehouse No Account - _TC" - si = frappe.copy_doc(si_doclist) + si = frappe.copy_doc(si_doc) si.insert() si.submit() @@ -530,9 +530,9 @@ class TestSalesInvoice(unittest.TestCase): expected_gl_entries = sorted([ [si.debit_to, 630.0, 0.0], - [si_doclist[1]["income_account"], 0.0, 500.0], - [si_doclist[2]["account_head"], 0.0, 80.0], - [si_doclist[3]["account_head"], 0.0, 50.0], + [si_doc.get("entries")["income_account"], 0.0, 500.0], + [si_doc.get("other_charges")[0]["account_head"], 0.0, 80.0], + [si_doc.get("other_charges")[1]["account_head"], 0.0, 50.0], ]) for i, gle in enumerate(gl_entries): self.assertEquals(expected_gl_entries[i][0], gle.account) @@ -638,7 +638,7 @@ class TestSalesInvoice(unittest.TestCase): si.append("advance_adjustment_details", { "doctype": "Sales Invoice Advance", "journal_voucher": jv.name, - "jv_detail_no": jv.doclist[1].name, + "jv_detail_no": jv.get("entries")[0].name, "advance_amount": 400, "allocated_amount": 300, "remarks": jv.remark @@ -677,13 +677,13 @@ class TestSalesInvoice(unittest.TestCase): }) # monthly - si1 = frappe.copy_doc(base_si.doclist) + si1 = frappe.copy_doc(base_si) si1.insert() si1.submit() self._test_recurring_invoice(si1, True) # monthly without a first and last day period - si2 = frappe.copy_doc(base_si.doclist) + si2 = frappe.copy_doc(base_si) si2.update({ "invoice_period_from_date": today, "invoice_period_to_date": add_to_date(today, days=30) @@ -693,7 +693,7 @@ class TestSalesInvoice(unittest.TestCase): self._test_recurring_invoice(si2, False) # quarterly - si3 = frappe.copy_doc(base_si.doclist) + si3 = frappe.copy_doc(base_si) si3.update({ "recurring_type": "Quarterly", "invoice_period_from_date": get_first_day(today), @@ -704,7 +704,7 @@ class TestSalesInvoice(unittest.TestCase): self._test_recurring_invoice(si3, True) # quarterly without a first and last day period - si4 = frappe.copy_doc(base_si.doclist) + si4 = frappe.copy_doc(base_si) si4.update({ "recurring_type": "Quarterly", "invoice_period_from_date": today, @@ -715,7 +715,7 @@ class TestSalesInvoice(unittest.TestCase): self._test_recurring_invoice(si4, False) # yearly - si5 = frappe.copy_doc(base_si.doclist) + si5 = frappe.copy_doc(base_si) si5.update({ "recurring_type": "Yearly", "invoice_period_from_date": get_first_day(today), @@ -726,7 +726,7 @@ class TestSalesInvoice(unittest.TestCase): self._test_recurring_invoice(si5, True) # yearly without a first and last day period - si6 = frappe.copy_doc(base_si.doclist) + si6 = frappe.copy_doc(base_si) si6.update({ "recurring_type": "Yearly", "invoice_period_from_date": today, @@ -737,7 +737,7 @@ class TestSalesInvoice(unittest.TestCase): self._test_recurring_invoice(si6, False) # change posting date but keep recuring day to be today - si7 = frappe.copy_doc(base_si.doclist) + si7 = frappe.copy_doc(base_si) si7.update({ "posting_date": add_to_date(today, days=-1) }) @@ -808,13 +808,13 @@ class TestSalesInvoice(unittest.TestCase): from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos se = make_serialized_item() - serial_nos = get_serial_nos(se.doclist[1].serial_no) + serial_nos = get_serial_nos(se.get("entries")[0].serial_no) si = frappe.copy_doc(test_records[0]) si.update_stock = 1 - si.doclist[1].item_code = "_Test Serialized Item With Series" - si.doclist[1].qty = 1 - si.doclist[1].serial_no = serial_nos[0] + si.get("entries")[0].item_code = "_Test Serialized Item With Series" + si.get("entries")[0].qty = 1 + si.get("entries")[0].serial_no = serial_nos[0] si.insert() si.submit() @@ -830,7 +830,7 @@ class TestSalesInvoice(unittest.TestCase): si = self.test_serialized() si.cancel() - serial_nos = get_serial_nos(si.doclist[1].serial_no) + serial_nos = get_serial_nos(si.get("entries")[0].serial_no) self.assertEquals(frappe.db.get_value("Serial No", serial_nos[0], "status"), "Available") self.assertEquals(frappe.db.get_value("Serial No", serial_nos[0], "warehouse"), "_Test Warehouse - _TC") @@ -842,7 +842,7 @@ class TestSalesInvoice(unittest.TestCase): from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item se = make_serialized_item() - serial_nos = get_serial_nos(se.doclist[1].serial_no) + serial_nos = get_serial_nos(se.get("entries")[0].serial_no) sr = frappe.get_doc("Serial No", serial_nos[0]) sr.status = "Not Available" @@ -850,9 +850,9 @@ class TestSalesInvoice(unittest.TestCase): si = frappe.copy_doc(test_records[0]) si.update_stock = 1 - si.doclist[1].item_code = "_Test Serialized Item With Series" - si.doclist[1].qty = 1 - si.doclist[1].serial_no = serial_nos[0] + si.get("entries")[0].item_code = "_Test Serialized Item With Series" + si.get("entries")[0].qty = 1 + si.get("entries")[0].serial_no = serial_nos[0] si.insert() self.assertRaises(SerialNoStatusError, si.submit) diff --git a/erpnext/accounts/doctype/shipping_rule/test_shipping_rule.py b/erpnext/accounts/doctype/shipping_rule/test_shipping_rule.py index 9fee555213..c53689e453 100644 --- a/erpnext/accounts/doctype/shipping_rule/test_shipping_rule.py +++ b/erpnext/accounts/doctype/shipping_rule/test_shipping_rule.py @@ -10,12 +10,12 @@ test_records = frappe.get_test_records('Shipping Rule') class TestShippingRule(unittest.TestCase): def test_from_greater_than_to(self): shipping_rule = frappe.copy_doc(test_records[0]) - shipping_rule.doclist[1].from_value = 101 + shipping_rule.get("shipping_rule_conditions")[0].from_value = 101 self.assertRaises(FromGreaterThanToError, shipping_rule.insert) def test_many_zero_to_values(self): shipping_rule = frappe.copy_doc(test_records[0]) - shipping_rule.doclist[1].to_value = 0 + shipping_rule.get("shipping_rule_conditions")[0].to_value = 0 self.assertRaises(ManyBlankToValuesError, shipping_rule.insert) def test_overlapping_conditions(self): @@ -27,8 +27,8 @@ class TestShippingRule(unittest.TestCase): ((50, 150), (50, 150)), ]: shipping_rule = frappe.copy_doc(test_records[0]) - shipping_rule.doclist[1].from_value = range_a[0] - shipping_rule.doclist[1].to_value = range_a[1] - shipping_rule.doclist[2].from_value = range_b[0] - shipping_rule.doclist[2].to_value = range_b[1] + shipping_rule.get("shipping_rule_conditions")[0].from_value = range_a[0] + shipping_rule.get("shipping_rule_conditions")[0].to_value = range_a[1] + shipping_rule.get("shipping_rule_conditions")[1].from_value = range_b[0] + shipping_rule.get("shipping_rule_conditions")[1].to_value = range_b[1] self.assertRaises(OverlappingConditionError, shipping_rule.insert) \ No newline at end of file diff --git a/erpnext/buying/doctype/purchase_order/test_purchase_order.py b/erpnext/buying/doctype/purchase_order/test_purchase_order.py index 358023383d..f8b03f040b 100644 --- a/erpnext/buying/doctype/purchase_order/test_purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/test_purchase_order.py @@ -41,7 +41,7 @@ class TestPurchaseOrder(unittest.TestCase): po = frappe.get_doc("Purchase Order", po.name) po.is_subcontracted = "No" - po.doclist[1].item_code = "_Test Item" + po.get("po_details")[0].item_code = "_Test Item" po.submit() self.assertEquals(frappe.db.get_value("Bin", {"item_code": "_Test Item", @@ -107,7 +107,7 @@ class TestPurchaseOrder(unittest.TestCase): def test_uom_integer_validation(self): from erpnext.utilities.transaction_base import UOMMustBeIntegerError po = frappe.copy_doc(test_records[0]) - po.doclist[1].qty = 3.4 + po.get("po_details")[0].qty = 3.4 self.assertRaises(UOMMustBeIntegerError, po.insert) diff --git a/erpnext/buying/doctype/supplier_quotation/test_supplier_quotation.py b/erpnext/buying/doctype/supplier_quotation/test_supplier_quotation.py index d526fd15f6..708b5e7f7a 100644 --- a/erpnext/buying/doctype/supplier_quotation/test_supplier_quotation.py +++ b/erpnext/buying/doctype/supplier_quotation/test_supplier_quotation.py @@ -21,7 +21,7 @@ class TestPurchaseOrder(unittest.TestCase): po = make_purchase_order(sq.name) self.assertEquals(po[0]["doctype"], "Purchase Order") - self.assertEquals(len(po), len(sq.doclist)) + self.assertEquals(len(po), len(sq)) po[0]["naming_series"] = "_T-Purchase Order-" diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 24af1e35fa..ffe6a6a43b 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -369,7 +369,7 @@ class AccountsController(TransactionBase): 'voucher_type': self.doctype, 'voucher_no': self.name, 'aging_date': self.get("aging_date") or self.posting_date, - 'remarks': self.remarks, + 'remarks': self.get("remarks"), 'fiscal_year': self.fiscal_year, 'debit': 0, 'credit': 0, diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py index da37adbfe4..027bfd2ad8 100644 --- a/erpnext/controllers/selling_controller.py +++ b/erpnext/controllers/selling_controller.py @@ -336,8 +336,8 @@ class SellingController(StockController): 'qty': d.qty, 'reserved_qty': reserved_qty_for_main_item, 'uom': d.stock_uom, - 'batch_no': cstr(d.batch_no).strip(), - 'serial_no': cstr(d.serial_no).strip(), + 'batch_no': cstr(d.get("batch_no")).strip(), + 'serial_no': cstr(d.get("serial_no")).strip(), 'name': d.name })) return il diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py index 62262ee5c8..e5ad8c69d1 100644 --- a/erpnext/controllers/stock_controller.py +++ b/erpnext/controllers/stock_controller.py @@ -49,7 +49,7 @@ class StockController(AccountsController): "account": warehouse_account[sle.warehouse], "against": detail.expense_account, "cost_center": detail.cost_center, - "remarks": self.remarks or "Accounting Entry for Stock", + "remarks": self.get("remarks") or "Accounting Entry for Stock", "debit": flt(sle.stock_value_difference, 2) })) @@ -58,7 +58,7 @@ class StockController(AccountsController): "account": detail.expense_account, "against": warehouse_account[sle.warehouse], "cost_center": detail.cost_center, - "remarks": self.remarks or "Accounting Entry for Stock", + "remarks": self.get("remarks") or "Accounting Entry for Stock", "credit": flt(sle.stock_value_difference, 2) })) elif sle.warehouse not in warehouse_with_no_account: @@ -103,8 +103,15 @@ class StockController(AccountsController): for d in item_doclist: if d.item_code and d.item_code not in items: items.append(d.item_code) - if d.warehouse and d.warehouse not in warehouses: + + if d.get("warehouse") and d.warehouse not in warehouses: warehouses.append(d.warehouse) + + if self.doctype == "Stock Entry": + if d.get("s_warehouse") and d.s_warehouse not in warehouses: + warehouses.append(d.s_warehouse) + if d.get("t_warehouse") and d.t_warehouse not in warehouses: + warehouses.append(d.t_warehouse) warehouse_account = {wh: warehouse_account[wh] for wh in warehouses if warehouse_account.get(wh)} @@ -234,20 +241,20 @@ class StockController(AccountsController): def get_sl_entries(self, d, args): sl_dict = { "item_code": d.item_code, - "warehouse": d.warehouse, + "warehouse": d.get("warehouse", None), "posting_date": self.posting_date, "posting_time": self.posting_time, "voucher_type": self.doctype, "voucher_no": self.name, "voucher_detail_no": d.name, - "actual_qty": (self.docstatus==1 and 1 or -1)*flt(d.stock_qty), + "actual_qty": (self.docstatus==1 and 1 or -1)*flt(d.get("stock_qty")), "stock_uom": d.stock_uom, "incoming_rate": 0, "company": self.company, "fiscal_year": self.fiscal_year, "batch_no": cstr(d.batch_no).strip(), "serial_no": d.serial_no, - "project": d.project_name, + "project": d.get("project_name"), "is_cancelled": self.docstatus==2 and "Yes" or "No" } diff --git a/erpnext/manufacturing/doctype/production_order/test_production_order.py b/erpnext/manufacturing/doctype/production_order/test_production_order.py index d7d41988bb..81fc61661f 100644 --- a/erpnext/manufacturing/doctype/production_order/test_production_order.py +++ b/erpnext/manufacturing/doctype/production_order/test_production_order.py @@ -27,7 +27,7 @@ class TestProductionOrder(unittest.TestCase): mr1.submit() mr2 = frappe.copy_doc(se_test_records[0]) - mr2.doclist[1].item_code = "_Test Item Home Desktop 100" + mr2.get("mtn_details")[0].item_code = "_Test Item Home Desktop 100" mr2.insert() mr2.submit() diff --git a/erpnext/projects/doctype/time_log_batch/test_time_log_batch.py b/erpnext/projects/doctype/time_log_batch/test_time_log_batch.py index eaf498c2d6..004c3643ac 100644 --- a/erpnext/projects/doctype/time_log_batch/test_time_log_batch.py +++ b/erpnext/projects/doctype/time_log_batch/test_time_log_batch.py @@ -17,7 +17,7 @@ class TimeLogBatchTest(unittest.TestCase): self.assertEquals(frappe.db.get_value("Time Log", time_log.name, "status"), "Submitted") tlb = frappe.copy_doc(test_records[0]) - tlb.doclist[1].time_log = time_log.name + tlb["time_log_batch_details"][0].time_log = time_log.name tlb.insert() tlb.submit() diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py index 435ad65757..af52028461 100644 --- a/erpnext/selling/doctype/sales_order/test_sales_order.py +++ b/erpnext/selling/doctype/sales_order/test_sales_order.py @@ -22,7 +22,7 @@ class TestSalesOrder(unittest.TestCase): mr = make_material_request(so.name) self.assertEquals(mr[0]["material_request_type"], "Purchase") - self.assertEquals(len(mr), len(sales_order.doclist)) + self.assertEquals(len(mr), len(sales_order)) def test_make_delivery_note(self): from erpnext.selling.doctype.sales_order.sales_order import make_delivery_note @@ -37,7 +37,7 @@ class TestSalesOrder(unittest.TestCase): dn = make_delivery_note(so.name) self.assertEquals(dn[0]["doctype"], "Delivery Note") - self.assertEquals(len(dn), len(sales_order.doclist)) + self.assertEquals(len(dn), len(sales_order)) def test_make_sales_invoice(self): from erpnext.selling.doctype.sales_order.sales_order import make_sales_invoice @@ -52,7 +52,7 @@ class TestSalesOrder(unittest.TestCase): si = make_sales_invoice(so.name) self.assertEquals(si[0]["doctype"], "Sales Invoice") - self.assertEquals(len(si), len(sales_order.doclist)) + self.assertEquals(len(si), len(sales_order)) self.assertEquals(len([d for d in si if d["doctype"]=="Sales Invoice Item"]), 1) si = frappe.get_doc(si) @@ -64,11 +64,11 @@ class TestSalesOrder(unittest.TestCase): self.assertEquals(len([d for d in si1 if d["doctype"]=="Sales Invoice Item"]), 0) - def create_so(self, so_doclist = None): - if not so_doclist: - so_doclist = test_records[0] + def create_so(self, so_doc = None): + if not so_doc: + so_doc = test_records[0] - w = frappe.copy_doc(so_doclist) + w = frappe.copy_doc(so_doc) w.insert() w.submit() @@ -78,14 +78,14 @@ class TestSalesOrder(unittest.TestCase): from erpnext.stock.doctype.delivery_note.test_delivery_note import test_records as dn_test_records from erpnext.stock.doctype.delivery_note.test_delivery_note import _insert_purchase_receipt - _insert_purchase_receipt(so.doclist[1].item_code) + _insert_purchase_receipt(so.get("sales_order_details")[0].item_code) dn = frappe.get_doc(frappe.copy_doc(dn_test_records[0])) - dn.doclist[1].item_code = so.doclist[1].item_code - dn.doclist[1].against_sales_order = so.name - dn.doclist[1].prevdoc_detail_docname = so.doclist[1].name + dn.get("delivery_note_details")[0].item_code = so.get("sales_order_details")[0].item_code + dn.get("delivery_note_details")[0].against_sales_order = so.name + dn.get("delivery_note_details")[0].prevdoc_detail_docname = so.get("sales_order_details")[0].name if delivered_qty: - dn.doclist[1].qty = delivered_qty + dn.get("delivery_note_details")[0].qty = delivered_qty dn.insert() dn.submit() return dn @@ -110,11 +110,11 @@ class TestSalesOrder(unittest.TestCase): # submit so = self.create_so() - self.check_reserved_qty(so.doclist[1].item_code, so.doclist[1].warehouse, 10.0) + self.check_reserved_qty(so.get("sales_order_details")[0].item_code, so.get("sales_order_details")[0].warehouse, 10.0) # cancel so.cancel() - self.check_reserved_qty(so.doclist[1].item_code, so.doclist[1].warehouse, 0.0) + self.check_reserved_qty(so.get("sales_order_details")[0].item_code, so.get("sales_order_details")[0].warehouse, 0.0) def test_reserved_qty_for_partial_delivery(self): @@ -130,21 +130,21 @@ class TestSalesOrder(unittest.TestCase): # submit dn dn = self.create_dn_against_so(so) - self.check_reserved_qty(so.doclist[1].item_code, so.doclist[1].warehouse, 5.0) + self.check_reserved_qty(so.get("sales_order_details")[0].item_code, so.get("sales_order_details")[0].warehouse, 5.0) # stop so so.load_from_db() so.obj.stop_sales_order() - self.check_reserved_qty(so.doclist[1].item_code, so.doclist[1].warehouse, 0.0) + self.check_reserved_qty(so.get("sales_order_details")[0].item_code, so.get("sales_order_details")[0].warehouse, 0.0) # unstop so so.load_from_db() so.obj.unstop_sales_order() - self.check_reserved_qty(so.doclist[1].item_code, so.doclist[1].warehouse, 5.0) + self.check_reserved_qty(so.get("sales_order_details")[0].item_code, so.get("sales_order_details")[0].warehouse, 5.0) # cancel dn dn.cancel() - self.check_reserved_qty(so.doclist[1].item_code, so.doclist[1].warehouse, 10.0) + self.check_reserved_qty(so.get("sales_order_details")[0].item_code, so.get("sales_order_details")[0].warehouse, 10.0) def test_reserved_qty_for_over_delivery(self): # reset bin @@ -157,15 +157,15 @@ class TestSalesOrder(unittest.TestCase): frappe.db.set_default("allow_negative_stock", 1) # set over-delivery tolerance - frappe.db.set_value('Item', so.doclist[1].item_code, 'tolerance', 50) + frappe.db.set_value('Item', so.get("sales_order_details")[0].item_code, 'tolerance', 50) # submit dn dn = self.create_dn_against_so(so, 15) - self.check_reserved_qty(so.doclist[1].item_code, so.doclist[1].warehouse, 0.0) + self.check_reserved_qty(so.get("sales_order_details")[0].item_code, so.get("sales_order_details")[0].warehouse, 0.0) # cancel dn dn.cancel() - self.check_reserved_qty(so.doclist[1].item_code, so.doclist[1].warehouse, 10.0) + self.check_reserved_qty(so.get("sales_order_details")[0].item_code, so.get("sales_order_details")[0].warehouse, 10.0) def test_reserved_qty_for_so_with_packing_list(self): from erpnext.selling.doctype.sales_bom.test_sales_bom import test_records as sbom_test_records @@ -183,16 +183,16 @@ class TestSalesOrder(unittest.TestCase): self.check_reserved_qty(sbom_test_records[0][1]["item_code"], - so.doclist[1].warehouse, 50.0) + so.get("sales_order_details")[0].warehouse, 50.0) self.check_reserved_qty(sbom_test_records[0][2]["item_code"], - so.doclist[1].warehouse, 20.0) + so.get("sales_order_details")[0].warehouse, 20.0) # cancel so.cancel() self.check_reserved_qty(sbom_test_records[0][1]["item_code"], - so.doclist[1].warehouse, 0.0) + so.get("sales_order_details")[0].warehouse, 0.0) self.check_reserved_qty(sbom_test_records[0][2]["item_code"], - so.doclist[1].warehouse, 0.0) + so.get("sales_order_details")[0].warehouse, 0.0) def test_reserved_qty_for_partial_delivery_with_packing_list(self): from erpnext.selling.doctype.sales_bom.test_sales_bom import test_records as sbom_test_records @@ -216,33 +216,33 @@ class TestSalesOrder(unittest.TestCase): dn = self.create_dn_against_so(so) self.check_reserved_qty(sbom_test_records[0][1]["item_code"], - so.doclist[1].warehouse, 25.0) + so.get("sales_order_details")[0].warehouse, 25.0) self.check_reserved_qty(sbom_test_records[0][2]["item_code"], - so.doclist[1].warehouse, 10.0) + so.get("sales_order_details")[0].warehouse, 10.0) # stop so so.load_from_db() so.obj.stop_sales_order() self.check_reserved_qty(sbom_test_records[0][1]["item_code"], - so.doclist[1].warehouse, 0.0) + so.get("sales_order_details")[0].warehouse, 0.0) self.check_reserved_qty(sbom_test_records[0][2]["item_code"], - so.doclist[1].warehouse, 0.0) + so.get("sales_order_details")[0].warehouse, 0.0) # unstop so so.load_from_db() so.obj.unstop_sales_order() self.check_reserved_qty(sbom_test_records[0][1]["item_code"], - so.doclist[1].warehouse, 25.0) + so.get("sales_order_details")[0].warehouse, 25.0) self.check_reserved_qty(sbom_test_records[0][2]["item_code"], - so.doclist[1].warehouse, 10.0) + so.get("sales_order_details")[0].warehouse, 10.0) # cancel dn dn.cancel() self.check_reserved_qty(sbom_test_records[0][1]["item_code"], - so.doclist[1].warehouse, 50.0) + so.get("sales_order_details")[0].warehouse, 50.0) self.check_reserved_qty(sbom_test_records[0][2]["item_code"], - so.doclist[1].warehouse, 20.0) + so.get("sales_order_details")[0].warehouse, 20.0) def test_reserved_qty_for_over_delivery_with_packing_list(self): from erpnext.selling.doctype.sales_bom.test_sales_bom import test_records as sbom_test_records @@ -262,22 +262,22 @@ class TestSalesOrder(unittest.TestCase): frappe.db.set_default("allow_negative_stock", 1) # set over-delivery tolerance - frappe.db.set_value('Item', so.doclist[1].item_code, 'tolerance', 50) + frappe.db.set_value('Item', so.get("sales_order_details")[0].item_code, 'tolerance', 50) # submit dn dn = self.create_dn_against_so(so, 15) self.check_reserved_qty(sbom_test_records[0][1]["item_code"], - so.doclist[1].warehouse, 0.0) + so.get("sales_order_details")[0].warehouse, 0.0) self.check_reserved_qty(sbom_test_records[0][2]["item_code"], - so.doclist[1].warehouse, 0.0) + so.get("sales_order_details")[0].warehouse, 0.0) # cancel dn dn.cancel() self.check_reserved_qty(sbom_test_records[0][1]["item_code"], - so.doclist[1].warehouse, 50.0) + so.get("sales_order_details")[0].warehouse, 50.0) self.check_reserved_qty(sbom_test_records[0][2]["item_code"], - so.doclist[1].warehouse, 20.0) + so.get("sales_order_details")[0].warehouse, 20.0) def test_warehouse_user(self): frappe.defaults.add_default("Warehouse", "_Test Warehouse 1 - _TC1", "test@example.com", "Restriction") @@ -293,7 +293,7 @@ class TestSalesOrder(unittest.TestCase): so.company = "_Test Company 1" so.conversion_rate = 0.02 so.plc_conversion_rate = 0.02 - so.doclist[1].warehouse = "_Test Warehouse 2 - _TC1" + so.get("sales_order_details")[0].warehouse = "_Test Warehouse 2 - _TC1" self.assertRaises(frappe.PermissionError, so.insert) frappe.set_user("test2@example.com") diff --git a/erpnext/setup/install.py b/erpnext/setup/install.py index 94d435ecc6..5128e36e8c 100644 --- a/erpnext/setup/install.py +++ b/erpnext/setup/install.py @@ -137,8 +137,7 @@ def feature_setup(): doc.save() def set_single_defaults(): - for dt in frappe.db.sql_list("""select name from `tabDocType` - where issingle=1 and parent != '__default'"""): + for dt in frappe.db.sql_list("""select name from `tabDocType` where issingle=1"""): default_values = frappe.db.sql("""select fieldname, `default` from `tabDocField` where parent=%s""", dt) if default_values: diff --git a/erpnext/stock/doctype/bin/bin.py b/erpnext/stock/doctype/bin/bin.py index a5fd8ecfe6..3f74c5c7d3 100644 --- a/erpnext/stock/doctype/bin/bin.py +++ b/erpnext/stock/doctype/bin/bin.py @@ -3,16 +3,11 @@ from __future__ import unicode_literals import frappe -from frappe.utils import add_days, cint,flt, nowdate, get_url_to_form, formatdate -from frappe import msgprint, _ - +from frappe.utils import flt, nowdate import frappe.defaults - - from frappe.model.document import Document -class Bin(Document): - +class Bin(Document): def validate(self): if self.get("__islocal") or not self.stock_uom: self.stock_uom = frappe.db.get_value('Item', self.item_code, 'stock_uom') @@ -25,7 +20,7 @@ class Bin(Document): def validate_mandatory(self): qf = ['actual_qty', 'reserved_qty', 'ordered_qty', 'indented_qty'] for f in qf: - if (not self.has_key(f)) or (not self.get(f)): + if (not getattr(self, f, None)) or (not self.get(f)): self.set(f, 0.0) def update_stock(self, args): @@ -47,6 +42,7 @@ class Bin(Document): def update_qty(self, args): # update the stock values (for current quantities) + self.actual_qty = flt(self.actual_qty) + flt(args.get("actual_qty")) self.ordered_qty = flt(self.ordered_qty) + flt(args.get("ordered_qty")) self.reserved_qty = flt(self.reserved_qty) + flt(args.get("reserved_qty")) diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py index b9900632c7..347b1f4d81 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/delivery_note.py @@ -313,7 +313,7 @@ def make_sales_invoice(source_name, target_doc=None): "serial_no": "serial_no" }, "postprocess": update_item, - "filter": lambda d: d.qty - invoiced_qty_map.get(d.name, 0)==0 + "filter": lambda d: d.qty - invoiced_qty_map.get(d.name, 0)<=0 }, "Sales Taxes and Charges": { "doctype": "Sales Taxes and Charges", diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py index 1ee4993cec..0260232c4c 100644 --- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py @@ -14,7 +14,7 @@ def _insert_purchase_receipt(item_code=None): item_code = pr_test_records[0][1]["item_code"] pr = frappe.copy_doc(pr_test_records[0]) - pr.doclist[1].item_code = item_code + pr.get("purchase_receipt_details")[0].item_code = item_code pr.insert() pr.submit() @@ -34,7 +34,7 @@ class TestDeliveryNote(unittest.TestCase): dn.submit() si = make_sales_invoice(dn.name) - self.assertEquals(len(si), len(dn.doclist)) + self.assertEquals(len(si), len(dn)) # modify amount si[1]["rate"] = 200 @@ -69,11 +69,11 @@ class TestDeliveryNote(unittest.TestCase): _insert_purchase_receipt() dn = frappe.copy_doc(test_records[0]) - dn.doclist[1].expense_account = "Cost of Goods Sold - _TC" - dn.doclist[1].cost_center = "Main - _TC" + dn.get("delivery_note_details")[0].expense_account = "Cost of Goods Sold - _TC" + dn.get("delivery_note_details")[0].cost_center = "Main - _TC" stock_in_hand_account = frappe.db.get_value("Account", - {"master_name": dn.doclist[1].warehouse}) + {"master_name": dn.get("delivery_note_details")[0].warehouse}) from erpnext.accounts.utils import get_balance_on prev_bal = get_balance_on(stock_in_hand_account, dn.posting_date) @@ -97,8 +97,8 @@ class TestDeliveryNote(unittest.TestCase): # back dated purchase receipt pr = frappe.copy_doc(pr_test_records[0]) pr.posting_date = "2013-01-01" - pr.doclist[1].rate = 100 - pr.doclist[1].base_amount = 100 + pr.get("purchase_receipt_details")[0].rate = 100 + pr.get("purchase_receipt_details")[0].base_amount = 100 pr.insert() pr.submit() @@ -124,11 +124,11 @@ class TestDeliveryNote(unittest.TestCase): _insert_purchase_receipt("_Test Item Home Desktop 100") dn = frappe.copy_doc(test_records[0]) - dn.doclist[1].item_code = "_Test Sales BOM Item" - dn.doclist[1].qty = 1 + dn.get("delivery_note_details")[0].item_code = "_Test Sales BOM Item" + dn.get("delivery_note_details")[0].qty = 1 stock_in_hand_account = frappe.db.get_value("Account", - {"master_name": dn.doclist[1].warehouse}) + {"master_name": dn.get("delivery_note_details")[0].warehouse}) from erpnext.accounts.utils import get_balance_on prev_bal = get_balance_on(stock_in_hand_account, dn.posting_date) @@ -160,12 +160,12 @@ class TestDeliveryNote(unittest.TestCase): from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos se = make_serialized_item() - serial_nos = get_serial_nos(se.doclist[1].serial_no) + serial_nos = get_serial_nos(se.get("mtn_details")[0].serial_no) dn = frappe.copy_doc(test_records[0]) - dn.doclist[1].item_code = "_Test Serialized Item With Series" - dn.doclist[1].qty = 1 - dn.doclist[1].serial_no = serial_nos[0] + dn.get("delivery_note_details")[0].item_code = "_Test Serialized Item With Series" + dn.get("delivery_note_details")[0].qty = 1 + dn.get("delivery_note_details")[0].serial_no = serial_nos[0] dn.insert() dn.submit() @@ -181,7 +181,7 @@ class TestDeliveryNote(unittest.TestCase): dn = self.test_serialized() dn.cancel() - serial_nos = get_serial_nos(dn.doclist[1].serial_no) + serial_nos = get_serial_nos(dn.get("delivery_note_details")[0].serial_no) self.assertEquals(frappe.db.get_value("Serial No", serial_nos[0], "status"), "Available") self.assertEquals(frappe.db.get_value("Serial No", serial_nos[0], "warehouse"), "_Test Warehouse - _TC") @@ -193,16 +193,16 @@ class TestDeliveryNote(unittest.TestCase): from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item se = make_serialized_item() - serial_nos = get_serial_nos(se.doclist[1].serial_no) + serial_nos = get_serial_nos(se.get("mtn_details")[0].serial_no) sr = frappe.get_doc("Serial No", serial_nos[0]) sr.status = "Not Available" sr.save() dn = frappe.copy_doc(test_records[0]) - dn.doclist[1].item_code = "_Test Serialized Item With Series" - dn.doclist[1].qty = 1 - dn.doclist[1].serial_no = serial_nos[0] + dn.get("delivery_note_details")[0].item_code = "_Test Serialized Item With Series" + dn.get("delivery_note_details")[0].qty = 1 + dn.get("delivery_note_details")[0].serial_no = serial_nos[0] dn.insert() self.assertRaises(SerialNoStatusError, dn.submit) diff --git a/erpnext/stock/doctype/material_request/test_material_request.py b/erpnext/stock/doctype/material_request/test_material_request.py index 14b9f2821f..6d10d40059 100644 --- a/erpnext/stock/doctype/material_request/test_material_request.py +++ b/erpnext/stock/doctype/material_request/test_material_request.py @@ -25,7 +25,7 @@ class TestMaterialRequest(unittest.TestCase): po = make_purchase_order(mr.name) self.assertEquals(po[0]["doctype"], "Purchase Order") - self.assertEquals(len(po), len(mr.doclist)) + self.assertEquals(len(po), len(mr)) def test_make_supplier_quotation(self): from erpnext.stock.doctype.material_request.material_request import make_supplier_quotation @@ -40,7 +40,7 @@ class TestMaterialRequest(unittest.TestCase): sq = make_supplier_quotation(mr.name) self.assertEquals(sq[0]["doctype"], "Supplier Quotation") - self.assertEquals(len(sq), len(mr.doclist)) + self.assertEquals(len(sq), len(mr)) def test_make_stock_entry(self): @@ -57,12 +57,12 @@ class TestMaterialRequest(unittest.TestCase): se = make_stock_entry(mr.name) self.assertEquals(se[0]["doctype"], "Stock Entry") - self.assertEquals(len(se), len(mr.doclist)) + self.assertEquals(len(se), len(mr)) - def _test_expected(self, doclist, expected_values): + def _test_expected(self, doc, expected_values): for i, expected in enumerate(expected_values): for fieldname, val in expected.items(): - self.assertEquals(val, doclist[i].get(fieldname)) + self.assertEquals(val, doc[i].get(fieldname)) def _test_requested_qty(self, qty1, qty2): self.assertEqual(flt(frappe.db.get_value("Bin", {"item_code": "_Test Item Home Desktop 100", @@ -104,8 +104,7 @@ class TestMaterialRequest(unittest.TestCase): "t_warehouse": "_Test Warehouse 1 - _TC", } ] - }, - ]) + }) se.insert() se.submit() @@ -118,42 +117,42 @@ class TestMaterialRequest(unittest.TestCase): mr.submit() # check if per complete is None - self._test_expected(mr.doclist, [{"per_ordered": None}, {"ordered_qty": None}, {"ordered_qty": None}]) + self._test_expected(mr, [{"per_ordered": None}, {"ordered_qty": None}, {"ordered_qty": None}]) self._test_requested_qty(54.0, 3.0) # map a purchase order from erpnext.stock.doctype.material_request.material_request import make_purchase_order - po_doclist = make_purchase_order(mr.name) - po_doclist[0]["supplier"] = "_Test Supplier" - po_doclist[0]["transaction_date"] = "2013-07-07" - po_doclist[1]["qty"] = 27.0 - po_doclist[2]["qty"] = 1.5 - po_doclist[1]["schedule_date"] = "2013-07-09" - po_doclist[2]["schedule_date"] = "2013-07-09" + po_doc = make_purchase_order(mr.name) + po_doc["supplier"] = "_Test Supplier" + po_doc["transaction_date"] = "2013-07-07" + po_doc.get("po_details")[0]["qty"] = 27.0 + po_doc.get("po_details")[1]["qty"] = 1.5 + po_doc.get("po_details")[0]["schedule_date"] = "2013-07-09" + po_doc.get("po_details")[1]["schedule_date"] = "2013-07-09" # check for stopped status of Material Request - po = frappe.copy_doc(po_doclist) + po = frappe.copy_doc(po_doc) po.insert() mr.obj.update_status('Stopped') self.assertRaises(frappe.ValidationError, po.submit) self.assertRaises(frappe.ValidationError, po.cancel) mr.obj.update_status('Submitted') - po = frappe.copy_doc(po_doclist) + po = frappe.copy_doc(po_doc) po.insert() po.submit() # check if per complete is as expected mr.load_from_db() - self._test_expected(mr.doclist, [{"per_ordered": 50}, {"ordered_qty": 27.0}, {"ordered_qty": 1.5}]) + self._test_expected(mr, [{"per_ordered": 50}, {"ordered_qty": 27.0}, {"ordered_qty": 1.5}]) self._test_requested_qty(27.0, 1.5) po.cancel() # check if per complete is as expected mr.load_from_db() - self._test_expected(mr.doclist, [{"per_ordered": None}, {"ordered_qty": None}, {"ordered_qty": None}]) + self._test_expected(mr, [{"per_ordered": None}, {"ordered_qty": None}, {"ordered_qty": None}]) self._test_requested_qty(54.0, 3.0) def test_completed_qty_for_transfer(self): @@ -167,26 +166,26 @@ class TestMaterialRequest(unittest.TestCase): mr.submit() # check if per complete is None - self._test_expected(mr.doclist, [{"per_ordered": None}, {"ordered_qty": None}, {"ordered_qty": None}]) + self._test_expected(mr, [{"per_ordered": None}, {"ordered_qty": None}, {"ordered_qty": None}]) self._test_requested_qty(54.0, 3.0) from erpnext.stock.doctype.material_request.material_request import make_stock_entry # map a stock entry - se_doclist = make_stock_entry(mr.name) - se_doclist[0].update({ + se_doc = make_stock_entry(mr.name) + se_doc.update({ "posting_date": "2013-03-01", "posting_time": "01:00", "fiscal_year": "_Test Fiscal Year 2013", }) - se_doclist[1].update({ + se_doc.get("mtn_details")[0].update({ "qty": 27.0, "transfer_qty": 27.0, "s_warehouse": "_Test Warehouse 1 - _TC", "incoming_rate": 1.0 }) - se_doclist[2].update({ + se_doc.get("mtn_details")[1].update({ "qty": 1.5, "transfer_qty": 1.5, "s_warehouse": "_Test Warehouse 1 - _TC", @@ -197,26 +196,26 @@ class TestMaterialRequest(unittest.TestCase): self._insert_stock_entry(27.0, 1.5) # check for stopped status of Material Request - se = frappe.copy_doc(se_doclist) + se = frappe.copy_doc(se_doc) se.insert() mr.obj.update_status('Stopped') self.assertRaises(frappe.ValidationError, se.submit) self.assertRaises(frappe.ValidationError, se.cancel) mr.obj.update_status('Submitted') - se = frappe.copy_doc(se_doclist) + se = frappe.copy_doc(se_doc) se.insert() se.submit() # check if per complete is as expected mr.load_from_db() - self._test_expected(mr.doclist, [{"per_ordered": 50}, {"ordered_qty": 27.0}, {"ordered_qty": 1.5}]) + self._test_expected(mr, [{"per_ordered": 50}, {"ordered_qty": 27.0}, {"ordered_qty": 1.5}]) self._test_requested_qty(27.0, 1.5) # check if per complete is as expected for Stock Entry cancelled se.cancel() mr.load_from_db() - self._test_expected(mr.doclist, [{"per_ordered": 0}, {"ordered_qty": 0}, {"ordered_qty": 0}]) + self._test_expected(mr, [{"per_ordered": 0}, {"ordered_qty": 0}, {"ordered_qty": 0}]) self._test_requested_qty(54.0, 3.0) def test_completed_qty_for_over_transfer(self): @@ -230,26 +229,26 @@ class TestMaterialRequest(unittest.TestCase): mr.submit() # check if per complete is None - self._test_expected(mr.doclist, [{"per_ordered": None}, {"ordered_qty": None}, {"ordered_qty": None}]) + self._test_expected(mr, [{"per_ordered": None}, {"ordered_qty": None}, {"ordered_qty": None}]) self._test_requested_qty(54.0, 3.0) # map a stock entry from erpnext.stock.doctype.material_request.material_request import make_stock_entry - se_doclist = make_stock_entry(mr.name) - se_doclist[0].update({ + se_doc = make_stock_entry(mr.name) + se_doc.update({ "posting_date": "2013-03-01", "posting_time": "00:00", "fiscal_year": "_Test Fiscal Year 2013", }) - se_doclist[1].update({ + se_doc.get("mtn_details")[0].update({ "qty": 60.0, "transfer_qty": 60.0, "s_warehouse": "_Test Warehouse 1 - _TC", "incoming_rate": 1.0 }) - se_doclist[2].update({ + se_doc.get("mtn_details")[1].update({ "qty": 3.0, "transfer_qty": 3.0, "s_warehouse": "_Test Warehouse 1 - _TC", @@ -260,26 +259,26 @@ class TestMaterialRequest(unittest.TestCase): self._insert_stock_entry(60.0, 3.0) # check for stopped status of Material Request - se = frappe.copy_doc(se_doclist) + se = frappe.copy_doc(se_doc) se.insert() mr.obj.update_status('Stopped') self.assertRaises(frappe.ValidationError, se.submit) self.assertRaises(frappe.ValidationError, se.cancel) mr.obj.update_status('Submitted') - se = frappe.copy_doc(se_doclist) + se = frappe.copy_doc(se_doc) se.insert() se.submit() # check if per complete is as expected mr.load_from_db() - self._test_expected(mr.doclist, [{"per_ordered": 100}, {"ordered_qty": 60.0}, {"ordered_qty": 3.0}]) + self._test_expected(mr, [{"per_ordered": 100}, {"ordered_qty": 60.0}, {"ordered_qty": 3.0}]) self._test_requested_qty(0.0, 0.0) # check if per complete is as expected for Stock Entry cancelled se.cancel() mr.load_from_db() - self._test_expected(mr.doclist, [{"per_ordered": 0}, {"ordered_qty": 0}, {"ordered_qty": 0}]) + self._test_expected(mr, [{"per_ordered": 0}, {"ordered_qty": 0}, {"ordered_qty": 0}]) self._test_requested_qty(54.0, 3.0) def test_incorrect_mapping_of_stock_entry(self): @@ -292,20 +291,20 @@ class TestMaterialRequest(unittest.TestCase): # map a stock entry from erpnext.stock.doctype.material_request.material_request import make_stock_entry - se_doclist = make_stock_entry(mr.name) - se_doclist[0].update({ + se_doc = make_stock_entry(mr.name) + se_doc.update({ "posting_date": "2013-03-01", "posting_time": "00:00", "fiscal_year": "_Test Fiscal Year 2013", }) - se_doclist[1].update({ + se_doc.get("mtn_details")[0].update({ "qty": 60.0, "transfer_qty": 60.0, "s_warehouse": "_Test Warehouse - _TC", "t_warehouse": "_Test Warehouse 1 - _TC", "incoming_rate": 1.0 }) - se_doclist[2].update({ + se_doc.get("mtn_details")[1].update({ "qty": 3.0, "transfer_qty": 3.0, "s_warehouse": "_Test Warehouse 1 - _TC", @@ -313,7 +312,7 @@ class TestMaterialRequest(unittest.TestCase): }) # check for stopped status of Material Request - se = frappe.copy_doc(se_doclist) + se = frappe.copy_doc(se_doc) self.assertRaises(frappe.MappingMismatchError, se.insert) def test_warehouse_company_validation(self): diff --git a/erpnext/stock/doctype/packed_item/packed_item.py b/erpnext/stock/doctype/packed_item/packed_item.py index 5a09121b4f..cf208ee87d 100644 --- a/erpnext/stock/doctype/packed_item/packed_item.py +++ b/erpnext/stock/doctype/packed_item/packed_item.py @@ -53,7 +53,7 @@ def update_packing_list_item(obj, packing_item_code, qty, warehouse, line, packi if not pi.warehouse: pi.warehouse = warehouse if not pi.batch_no: - pi.batch_no = cstr(line.batch_no) + pi.batch_no = cstr(line.get("batch_no")) pi.idx = packing_list_idx packing_list_idx += 1 diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py index 4c2b3a001c..f0de633ca6 100644 --- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py @@ -23,11 +23,11 @@ class TestPurchaseReceipt(unittest.TestCase): pr.submit() pi = make_purchase_invoice(pr.name) - self.assertEquals(pi[0]["doctype"], "Purchase Invoice") - self.assertEquals(len(pi), len(pr.doclist)) + self.assertEquals(pi["doctype"], "Purchase Invoice") + self.assertEquals(len(pi.get("entries")), len(pr.get("purchase_receipt_details"))) # modify rate - pi[1]["rate"] = 200 + pi.get("entries")[0]["rate"] = 200 self.assertRaises(frappe.ValidationError, frappe.get_doc(pi).submit) def test_purchase_receipt_no_gl_entry(self): @@ -65,9 +65,9 @@ class TestPurchaseReceipt(unittest.TestCase): self.assertTrue(gl_entries) stock_in_hand_account = frappe.db.get_value("Account", - {"master_name": pr.doclist[1].warehouse}) + {"master_name": pr.get("purchase_receipt_details")[0].warehouse}) fixed_asset_account = frappe.db.get_value("Account", - {"master_name": pr.doclist[2].warehouse}) + {"master_name": pr.get("purchase_receipt_details")[1].warehouse}) expected_values = { stock_in_hand_account: [375.0, 0.0], @@ -94,18 +94,18 @@ class TestPurchaseReceipt(unittest.TestCase): pr.run_method("calculate_taxes_and_totals") pr.insert() - self.assertEquals(pr.doclist[1].rm_supp_cost, 70000.0) + self.assertEquals(pr.get("purchase_receipt_details")[0].rm_supp_cost, 70000.0) self.assertEquals(len(pr.get("pr_raw_material_details")), 2) def test_serial_no_supplier(self): pr = frappe.copy_doc(test_records[0]) - pr.doclist[1].item_code = "_Test Serialized Item With Series" - pr.doclist[1].qty = 1 - pr.doclist[1].received_qty = 1 + pr.get("purchase_receipt_details")[0].item_code = "_Test Serialized Item With Series" + pr.get("purchase_receipt_details")[0].qty = 1 + pr.get("purchase_receipt_details")[0].received_qty = 1 pr.insert() pr.submit() - self.assertEquals(frappe.db.get_value("Serial No", pr.doclist[1].serial_no, + self.assertEquals(frappe.db.get_value("Serial No", pr.get("purchase_receipt_details")[0].serial_no, "supplier"), pr.supplier) return pr @@ -114,7 +114,7 @@ class TestPurchaseReceipt(unittest.TestCase): pr = self.test_serial_no_supplier() pr.cancel() - self.assertFalse(frappe.db.get_value("Serial No", pr.doclist[1].serial_no, + self.assertFalse(frappe.db.get_value("Serial No", pr.get("purchase_receipt_details")[0].serial_no, "warehouse")) def get_gl_entries(voucher_type, voucher_no): diff --git a/erpnext/stock/doctype/serial_no/serial_no.py b/erpnext/stock/doctype/serial_no/serial_no.py index 7a259f8e1f..90786550a4 100644 --- a/erpnext/stock/doctype/serial_no/serial_no.py +++ b/erpnext/stock/doctype/serial_no/serial_no.py @@ -284,6 +284,7 @@ def make_serial_no(serial_no, sle): sr.serial_no = serial_no sr.item_code = sle.item_code sr.warehouse = None + sr.company = sle.company sr.via_stock_ledger = True sr.insert() sr.warehouse = sle.warehouse diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index cdfff04430..b5d46a2c0f 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -277,7 +277,7 @@ class StockEntry(StockController): raise_exception=frappe.DoesNotExistError) # validate quantity <= ref item's qty - qty already returned - ref_item = ref.getone({"item_code": item.item_code}) + ref_item = ref.doc.getone({"item_code": item.item_code}) returnable_qty = ref_item.qty - flt(already_returned_item_qty.get(item.item_code)) if not returnable_qty: frappe.throw("{item}: {item_code} {returned}".format( @@ -710,7 +710,7 @@ def get_stock_items_for_return(ref_doc, parentfields): parentfields = [parentfields] all_items = list(set([d.item_code for d in - ref_doc.get_all_children() if d.item_code])) + ref_doc.get_all_children() if d.get("item_code")])) stock_items = frappe.db.sql_list("""select name from `tabItem` where is_stock_item='Yes' and name in (%s)""" % (", ".join(["%s"] * len(all_items))), tuple(all_items)) @@ -720,9 +720,9 @@ def get_stock_items_for_return(ref_doc, parentfields): def get_return_doc_and_details(args): ref = frappe._dict() - # get ref_doc + # get ref_doc if args.get("purpose") in return_map: - for fieldname, val in return_map[args["purpose"]].items(): + for fieldname, val in return_map[args.get("purpose")].items(): if args.get(fieldname): ref.fieldname = fieldname ref.doc = frappe.get_doc(val[0], args.get(fieldname)) diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py index 8c764ee892..0aa043333e 100644 --- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals import frappe, unittest -from frappe.utils import flt +from frappe.utils import flt, getdate from erpnext.stock.doctype.serial_no.serial_no import * from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory from erpnext.stock.doctype.stock_ledger_entry.stock_ledger_entry import StockFreezeError @@ -29,7 +29,7 @@ class TestStockEntry(unittest.TestCase): st2 = frappe.copy_doc(test_records[1]) st2.insert() st2.submit() - + from erpnext.stock.utils import reorder_item reorder_item() @@ -50,7 +50,7 @@ class TestStockEntry(unittest.TestCase): mr.submit() stock_in_hand_account = frappe.db.get_value("Account", {"account_type": "Warehouse", - "master_name": mr.doclist[1].t_warehouse}) + "master_name": mr.get("mtn_details")[0].t_warehouse}) self.check_stock_ledger_entries("Stock Entry", mr.name, [["_Test Item", "_Test Warehouse - _TC", 50.0]]) @@ -85,7 +85,7 @@ class TestStockEntry(unittest.TestCase): [["_Test Item", "_Test Warehouse - _TC", -40.0]]) stock_in_hand_account = frappe.db.get_value("Account", {"account_type": "Warehouse", - "master_name": mi.doclist[1].s_warehouse}) + "master_name": mi.get("mtn_details")[0].s_warehouse}) self.check_gl_entries("Stock Entry", mi.name, sorted([ @@ -101,11 +101,11 @@ class TestStockEntry(unittest.TestCase): self.assertFalse(frappe.db.sql("""select * from `tabGL Entry` where voucher_type='Stock Entry' and voucher_no=%s""", mi.name)) - self.assertEquals(frappe.db.get_value("Bin", {"warehouse": mi.doclist[1].s_warehouse, - "item_code": mi.doclist[1].item_code}, "actual_qty"), 50) + self.assertEquals(frappe.db.get_value("Bin", {"warehouse": mi.get("mtn_details")[0].s_warehouse, + "item_code": mi.get("mtn_details")[0].item_code}, "actual_qty"), 50) - self.assertEquals(frappe.db.get_value("Bin", {"warehouse": mi.doclist[1].s_warehouse, - "item_code": mi.doclist[1].item_code}, "stock_value"), 5000) + self.assertEquals(frappe.db.get_value("Bin", {"warehouse": mi.get("mtn_details")[0].s_warehouse, + "item_code": mi.get("mtn_details")[0].item_code}, "stock_value"), 5000) def test_material_transfer_gl_entry(self): self._clear_stock_account_balance() @@ -121,10 +121,10 @@ class TestStockEntry(unittest.TestCase): [["_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", - "master_name": mtn.doclist[1].s_warehouse}) + "master_name": mtn.get("mtn_details")[0].s_warehouse}) fixed_asset_account = frappe.db.get_value("Account", {"account_type": "Warehouse", - "master_name": mtn.doclist[1].t_warehouse}) + "master_name": mtn.get("mtn_details")[0].t_warehouse}) self.check_gl_entries("Stock Entry", mtn.name, @@ -171,12 +171,12 @@ class TestStockEntry(unittest.TestCase): self._insert_material_receipt() repack = frappe.copy_doc(test_records[3]) - repack.doclist[2].incoming_rate = 6000 + repack.get("mtn_details")[1].incoming_rate = 6000 repack.insert() repack.submit() stock_in_hand_account = frappe.db.get_value("Account", {"account_type": "Warehouse", - "master_name": repack.doclist[2].t_warehouse}) + "master_name": repack.get("mtn_details")[1].t_warehouse}) self.check_gl_entries("Stock Entry", repack.name, sorted([ @@ -223,7 +223,7 @@ class TestStockEntry(unittest.TestCase): se1.submit() se2 = frappe.copy_doc(test_records[0]) - se2.doclist[1].item_code = "_Test Item Home Desktop 100" + se2.get("mtn_details")[0].item_code = "_Test Item Home Desktop 100" se2.insert() se2.submit() @@ -235,7 +235,7 @@ class TestStockEntry(unittest.TestCase): def _test_sales_invoice_return(self, item_code, delivered_qty, returned_qty): from erpnext.stock.doctype.stock_entry.stock_entry import NotUpdateStockError - + from erpnext.accounts.doctype.sales_invoice.test_sales_invoice \ import test_records as sales_invoice_test_records @@ -247,8 +247,8 @@ class TestStockEntry(unittest.TestCase): se = frappe.copy_doc(test_records[0]) se.purpose = "Sales Return" se.sales_invoice_no = si.name - se.doclist[1].qty = returned_qty - se.doclist[1].transfer_qty = returned_qty + se.get("mtn_details")[0].qty = returned_qty + se.get("mtn_details")[0].transfer_qty = returned_qty self.assertRaises(NotUpdateStockError, se.insert) self._insert_material_receipt() @@ -259,9 +259,9 @@ class TestStockEntry(unittest.TestCase): # insert a pos invoice with update stock si = frappe.copy_doc(sales_invoice_test_records[1]) si.is_pos = si.update_stock = 1 - si.doclist[1].warehouse = "_Test Warehouse - _TC" - si.doclist[1].item_code = item_code - si.doclist[1].qty = 5.0 + si.get("entries")[0].warehouse = "_Test Warehouse - _TC" + si.get("entries")[0].item_code = item_code + si.get("entries")[0].qty = 5.0 si.insert() si.submit() @@ -276,9 +276,9 @@ class TestStockEntry(unittest.TestCase): se.sales_invoice_no = si.name se.posting_date = "2013-03-10" se.fiscal_year = "_Test Fiscal Year 2013" - se.doclist[1].item_code = "_Test Item Home Desktop 200" - se.doclist[1].qty = returned_qty - se.doclist[1].transfer_qty = returned_qty + se.get("mtn_details")[0].item_code = "_Test Item Home Desktop 200" + se.get("mtn_details")[0].qty = returned_qty + se.get("mtn_details")[0].transfer_qty = returned_qty # check if stock entry gets submitted self.assertRaises(frappe.DoesNotExistError, se.insert) @@ -289,8 +289,8 @@ class TestStockEntry(unittest.TestCase): se.posting_date = "2013-03-10" se.fiscal_year = "_Test Fiscal Year 2013" se.sales_invoice_no = si.name - se.doclist[1].qty = returned_qty - se.doclist[1].transfer_qty = returned_qty + se.get("mtn_details")[0].qty = returned_qty + se.get("mtn_details")[0].transfer_qty = returned_qty # in both cases item code remains _Test Item when returning se.insert() @@ -322,7 +322,7 @@ class TestStockEntry(unittest.TestCase): actual_qty_0 = self._get_actual_qty() # make a delivery note based on this invoice dn = frappe.copy_doc(delivery_note_test_records[0]) - dn.doclist[1].item_code = item_code + dn.get("delivery_note_details")[0].item_code = item_code dn.insert() dn.submit() @@ -330,9 +330,9 @@ class TestStockEntry(unittest.TestCase): self.assertEquals(actual_qty_0 - delivered_qty, actual_qty_1) - si_doclist = make_sales_invoice(dn.name) + si_doc = make_sales_invoice(dn.name) - si = frappe.get_doc(si_doclist) + si = frappe.get_doc(si_doc) si.posting_date = dn.posting_date si.debit_to = "_Test Customer - _TC" for d in si.get("entries"): @@ -347,7 +347,7 @@ class TestStockEntry(unittest.TestCase): se.delivery_note_no = dn.name se.posting_date = "2013-03-10" se.fiscal_year = "_Test Fiscal Year 2013" - se.doclist[1].qty = se.doclist[1].transfer_qty = returned_qty + se.get("mtn_details")[0].qty = se.get("mtn_details")[0].transfer_qty = returned_qty se.insert() se.submit() @@ -409,28 +409,25 @@ class TestStockEntry(unittest.TestCase): from erpnext.selling.doctype.sales_order.sales_order import make_sales_invoice, make_delivery_note actual_qty_0 = self._get_actual_qty() - so = frappe.copy_doc(sales_order_test_records[0]) - so.doclist[1].item_code = item_code - so.doclist[1].qty = 5.0 + so.get("sales_order_details")[0].item_code = item_code + so.get("sales_order_details")[0].qty = 5.0 so.insert() so.submit() + dn_doc = make_delivery_note(so.name) - dn_doclist = make_delivery_note(so.name) - - dn = frappe.get_doc(dn_doclist) + dn = frappe.get_doc(dn_doc) dn.status = "Draft" dn.posting_date = so.delivery_date dn.insert() dn.submit() actual_qty_1 = self._get_actual_qty() - self.assertEquals(actual_qty_0 - delivered_qty, actual_qty_1) - si_doclist = make_sales_invoice(so.name) + si_doc = make_sales_invoice(so.name) - si = frappe.get_doc(si_doclist) + si = frappe.get_doc(si_doc) si.posting_date = dn.posting_date si.debit_to = "_Test Customer - _TC" for d in si.get("entries"): @@ -445,7 +442,7 @@ class TestStockEntry(unittest.TestCase): se.delivery_note_no = dn.name se.posting_date = "2013-03-10" se.fiscal_year = "_Test Fiscal Year 2013" - se.doclist[1].qty = se.doclist[1].transfer_qty = returned_qty + se.get("mtn_details")[0].qty = se.get("mtn_details")[0].transfer_qty = returned_qty se.insert() se.submit() @@ -464,7 +461,7 @@ class TestStockEntry(unittest.TestCase): import test_records as purchase_receipt_test_records from erpnext.stock.doctype.purchase_receipt.purchase_receipt import make_purchase_invoice - + # submit purchase receipt pr = frappe.copy_doc(purchase_receipt_test_records[0]) pr.insert() @@ -474,9 +471,9 @@ class TestStockEntry(unittest.TestCase): self.assertEquals(actual_qty_0 + 5, actual_qty_1) - pi_doclist = make_purchase_invoice(pr.name) + pi_doc = make_purchase_invoice(pr.name) - pi = frappe.get_doc(pi_doclist) + pi = frappe.get_doc(pi_doc) pi.posting_date = pr.posting_date pi.credit_to = "_Test Supplier - _TC" for d in pi.get("entries"): @@ -497,8 +494,8 @@ class TestStockEntry(unittest.TestCase): se.purchase_receipt_no = pr.name se.posting_date = "2013-03-01" se.fiscal_year = "_Test Fiscal Year 2013" - se.doclist[1].qty = se.doclist[1].transfer_qty = 5 - se.doclist[1].s_warehouse = "_Test Warehouse - _TC" + se.get("mtn_details")[0].qty = se.get("mtn_details")[0].transfer_qty = 5 + se.get("mtn_details")[0].s_warehouse = "_Test Warehouse - _TC" se.insert() se.submit() @@ -523,8 +520,8 @@ class TestStockEntry(unittest.TestCase): se.purchase_receipt_no = pr_docname se.posting_date = "2013-03-01" se.fiscal_year = "_Test Fiscal Year 2013" - se.doclist[1].qty = se.doclist[1].transfer_qty = 6 - se.doclist[1].s_warehouse = "_Test Warehouse - _TC" + se.get("mtn_details")[0].qty = se.get("mtn_details")[0].transfer_qty = 6 + se.get("mtn_details")[0].s_warehouse = "_Test Warehouse - _TC" self.assertRaises(StockOverReturnError, se.insert) @@ -551,24 +548,24 @@ class TestStockEntry(unittest.TestCase): self._clear_stock_account_balance() actual_qty_0 = self._get_actual_qty() - + from erpnext.buying.doctype.purchase_order.test_purchase_order \ import test_records as purchase_order_test_records - + from erpnext.buying.doctype.purchase_order.purchase_order import \ make_purchase_receipt, make_purchase_invoice # submit purchase receipt po = frappe.copy_doc(purchase_order_test_records[0]) po.is_subcontracted = None - po.doclist[1].item_code = "_Test Item" - po.doclist[1].rate = 50 + po.get("po_details")[0].item_code = "_Test Item" + po.get("po_details")[0].rate = 50 po.insert() po.submit() - pr_doclist = make_purchase_receipt(po.name) + pr_doc = make_purchase_receipt(po.name) - pr = frappe.get_doc(pr_doclist) + pr = frappe.get_doc(pr_doc) pr.posting_date = po.transaction_date pr.insert() pr.submit() @@ -577,9 +574,9 @@ class TestStockEntry(unittest.TestCase): self.assertEquals(actual_qty_0 + 10, actual_qty_1) - pi_doclist = make_purchase_invoice(po.name) + pi_doc = make_purchase_invoice(po.name) - pi = frappe.get_doc(pi_doclist) + pi = frappe.get_doc(pi_doc) pi.posting_date = pr.posting_date pi.credit_to = "_Test Supplier - _TC" for d in pi.get("entries"): @@ -599,8 +596,8 @@ class TestStockEntry(unittest.TestCase): se.purchase_receipt_no = pr.name se.posting_date = "2013-03-01" se.fiscal_year = "_Test Fiscal Year 2013" - se.doclist[1].qty = se.doclist[1].transfer_qty = 5 - se.doclist[1].s_warehouse = "_Test Warehouse - _TC" + se.get("mtn_details")[0].qty = se.get("mtn_details")[0].transfer_qty = 5 + se.get("mtn_details")[0].s_warehouse = "_Test Warehouse - _TC" se.insert() se.submit() @@ -622,43 +619,43 @@ class TestStockEntry(unittest.TestCase): def test_serial_no_not_reqd(self): se = frappe.copy_doc(test_records[0]) - se.doclist[1].serial_no = "ABCD" + se.get("mtn_details")[0].serial_no = "ABCD" se.insert() self.assertRaises(SerialNoNotRequiredError, se.submit) def test_serial_no_reqd(self): se = frappe.copy_doc(test_records[0]) - se.doclist[1].item_code = "_Test Serialized Item" - se.doclist[1].qty = 2 - se.doclist[1].transfer_qty = 2 + se.get("mtn_details")[0].item_code = "_Test Serialized Item" + se.get("mtn_details")[0].qty = 2 + se.get("mtn_details")[0].transfer_qty = 2 se.insert() self.assertRaises(SerialNoRequiredError, se.submit) def test_serial_no_qty_more(self): se = frappe.copy_doc(test_records[0]) - se.doclist[1].item_code = "_Test Serialized Item" - se.doclist[1].qty = 2 - se.doclist[1].serial_no = "ABCD\nEFGH\nXYZ" - se.doclist[1].transfer_qty = 2 + se.get("mtn_details")[0].item_code = "_Test Serialized Item" + se.get("mtn_details")[0].qty = 2 + se.get("mtn_details")[0].serial_no = "ABCD\nEFGH\nXYZ" + se.get("mtn_details")[0].transfer_qty = 2 se.insert() self.assertRaises(SerialNoQtyError, se.submit) def test_serial_no_qty_less(self): se = frappe.copy_doc(test_records[0]) - se.doclist[1].item_code = "_Test Serialized Item" - se.doclist[1].qty = 2 - se.doclist[1].serial_no = "ABCD" - se.doclist[1].transfer_qty = 2 + se.get("mtn_details")[0].item_code = "_Test Serialized Item" + se.get("mtn_details")[0].qty = 2 + se.get("mtn_details")[0].serial_no = "ABCD" + se.get("mtn_details")[0].transfer_qty = 2 se.insert() self.assertRaises(SerialNoQtyError, se.submit) def test_serial_no_transfer_in(self): self._clear_stock_account_balance() se = frappe.copy_doc(test_records[0]) - se.doclist[1].item_code = "_Test Serialized Item" - se.doclist[1].qty = 2 - se.doclist[1].serial_no = "ABCD\nEFGH" - se.doclist[1].transfer_qty = 2 + se.get("mtn_details")[0].item_code = "_Test Serialized Item" + se.get("mtn_details")[0].qty = 2 + se.get("mtn_details")[0].serial_no = "ABCD\nEFGH" + se.get("mtn_details")[0].transfer_qty = 2 se.insert() se.submit() @@ -672,12 +669,12 @@ class TestStockEntry(unittest.TestCase): self._clear_stock_account_balance() se = frappe.copy_doc(test_records[0]) se.purpose = "Material Issue" - se.doclist[1].item_code = "_Test Serialized Item" - se.doclist[1].qty = 2 - se.doclist[1].s_warehouse = "_Test Warehouse 1 - _TC" - se.doclist[1].t_warehouse = None - se.doclist[1].serial_no = "ABCD\nEFGH" - se.doclist[1].transfer_qty = 2 + se.get("mtn_details")[0].item_code = "_Test Serialized Item" + se.get("mtn_details")[0].qty = 2 + se.get("mtn_details")[0].s_warehouse = "_Test Warehouse 1 - _TC" + se.get("mtn_details")[0].t_warehouse = None + se.get("mtn_details")[0].serial_no = "ABCD\nEFGH" + se.get("mtn_details")[0].transfer_qty = 2 se.insert() self.assertRaises(SerialNoNotExistsError, se.submit) @@ -686,10 +683,10 @@ class TestStockEntry(unittest.TestCase): self.test_serial_by_series() se = frappe.copy_doc(test_records[0]) - se.doclist[1].item_code = "_Test Serialized Item With Series" - se.doclist[1].qty = 1 - se.doclist[1].serial_no = "ABCD00001" - se.doclist[1].transfer_qty = 1 + se.get("mtn_details")[0].item_code = "_Test Serialized Item With Series" + se.get("mtn_details")[0].qty = 1 + se.get("mtn_details")[0].serial_no = "ABCD00001" + se.get("mtn_details")[0].transfer_qty = 1 se.insert() self.assertRaises(SerialNoDuplicateError, se.submit) @@ -697,7 +694,7 @@ class TestStockEntry(unittest.TestCase): self._clear_stock_account_balance() se = make_serialized_item() - serial_nos = get_serial_nos(se.doclist[1].serial_no) + serial_nos = get_serial_nos(se.get("mtn_details")[0].serial_no) self.assertTrue(frappe.db.exists("Serial No", serial_nos[0])) self.assertTrue(frappe.db.exists("Serial No", serial_nos[1])) @@ -710,28 +707,28 @@ class TestStockEntry(unittest.TestCase): se = frappe.copy_doc(test_records[0]) se.purpose = "Material Transfer" - se.doclist[1].item_code = "_Test Serialized Item" - se.doclist[1].qty = 1 - se.doclist[1].transfer_qty = 1 - se.doclist[1].serial_no = "ABCD00001" - se.doclist[1].s_warehouse = "_Test Warehouse - _TC" - se.doclist[1].t_warehouse = "_Test Warehouse 1 - _TC" + se.get("mtn_details")[0].item_code = "_Test Serialized Item" + se.get("mtn_details")[0].qty = 1 + se.get("mtn_details")[0].transfer_qty = 1 + se.get("mtn_details")[0].serial_no = "ABCD00001" + se.get("mtn_details")[0].s_warehouse = "_Test Warehouse - _TC" + se.get("mtn_details")[0].t_warehouse = "_Test Warehouse 1 - _TC" se.insert() self.assertRaises(SerialNoItemError, se.submit) def test_serial_move(self): self._clear_stock_account_balance() se = make_serialized_item() - serial_no = get_serial_nos(se.doclist[1].serial_no)[0] + serial_no = get_serial_nos(se.get("mtn_details")[0].serial_no)[0] se = frappe.copy_doc(test_records[0]) se.purpose = "Material Transfer" - se.doclist[1].item_code = "_Test Serialized Item With Series" - se.doclist[1].qty = 1 - se.doclist[1].transfer_qty = 1 - se.doclist[1].serial_no = serial_no - se.doclist[1].s_warehouse = "_Test Warehouse - _TC" - se.doclist[1].t_warehouse = "_Test Warehouse 1 - _TC" + se.get("mtn_details")[0].item_code = "_Test Serialized Item With Series" + se.get("mtn_details")[0].qty = 1 + se.get("mtn_details")[0].transfer_qty = 1 + se.get("mtn_details")[0].serial_no = serial_no + se.get("mtn_details")[0].s_warehouse = "_Test Warehouse - _TC" + se.get("mtn_details")[0].t_warehouse = "_Test Warehouse 1 - _TC" se.insert() se.submit() self.assertTrue(frappe.db.get_value("Serial No", serial_no, "warehouse"), "_Test Warehouse 1 - _TC") @@ -745,12 +742,12 @@ class TestStockEntry(unittest.TestCase): se = frappe.copy_doc(test_records[0]) se.purpose = "Material Transfer" - se.doclist[1].item_code = "_Test Serialized Item With Series" - se.doclist[1].qty = 1 - se.doclist[1].transfer_qty = 1 - se.doclist[1].serial_no = "ABCD00001" - se.doclist[1].s_warehouse = "_Test Warehouse 1 - _TC" - se.doclist[1].t_warehouse = "_Test Warehouse - _TC" + se.get("mtn_details")[0].item_code = "_Test Serialized Item With Series" + se.get("mtn_details")[0].qty = 1 + se.get("mtn_details")[0].transfer_qty = 1 + se.get("mtn_details")[0].serial_no = "ABCD00001" + se.get("mtn_details")[0].s_warehouse = "_Test Warehouse 1 - _TC" + se.get("mtn_details")[0].t_warehouse = "_Test Warehouse - _TC" se.insert() self.assertRaises(SerialNoWarehouseError, se.submit) @@ -759,9 +756,9 @@ class TestStockEntry(unittest.TestCase): se = self.test_serial_by_series() se.cancel() - serial_no = get_serial_nos(se.doclist[1].serial_no)[0] + serial_no = get_serial_nos(se.get("mtn_details")[0].serial_no)[0] self.assertFalse(frappe.db.get_value("Serial No", serial_no, "warehouse")) - + def test_warehouse_company_validation(self): set_perpetual_inventory(0) self._clear_stock_account_balance() @@ -771,15 +768,15 @@ class TestStockEntry(unittest.TestCase): from erpnext.stock.utils import InvalidWarehouseCompany st1 = frappe.copy_doc(test_records[0]) - st1.doclist[1].t_warehouse="_Test Warehouse 2 - _TC1" + st1.get("mtn_details")[0].t_warehouse="_Test Warehouse 2 - _TC1" st1.insert() self.assertRaises(InvalidWarehouseCompany, st1.submit) - + # permission tests def test_warehouse_user(self): import frappe.defaults set_perpetual_inventory(0) - + frappe.defaults.add_default("Warehouse", "_Test Warehouse 1 - _TC1", "test@example.com", "Restriction") frappe.defaults.add_default("Warehouse", "_Test Warehouse 2 - _TC1", "test2@example.com", "Restriction") frappe.get_doc("User", "test@example.com")\ @@ -790,19 +787,19 @@ class TestStockEntry(unittest.TestCase): frappe.set_user("test@example.com") st1 = frappe.copy_doc(test_records[0]) st1.company = "_Test Company 1" - st1.doclist[1].t_warehouse="_Test Warehouse 2 - _TC1" - self.assertRaises(frappe.PermissionErrorp, st1.insert) + st1.get("mtn_details")[0].t_warehouse="_Test Warehouse 2 - _TC1" + self.assertRaises(frappe.PermissionError, st1.insert) frappe.set_user("test2@example.com") st1 = frappe.copy_doc(test_records[0]) st1.company = "_Test Company 1" - st1.doclist[1].t_warehouse="_Test Warehouse 2 - _TC1" + st1.get("mtn_details")[0].t_warehouse="_Test Warehouse 2 - _TC1" st1.insert() st1.submit() - + frappe.defaults.clear_default("Warehouse", "_Test Warehouse 1 - _TC1", "test@example.com", parenttype="Restriction") frappe.defaults.clear_default("Warehouse", "_Test Warehouse 2 - _TC1", "test2@example.com", parenttype="Restriction") - + def test_freeze_stocks (self): self._clear_stock_account_balance() frappe.db.set_value('Stock Settings', None,'stock_auth_role', '') @@ -822,11 +819,11 @@ class TestStockEntry(unittest.TestCase): def make_serialized_item(): se = frappe.copy_doc(test_records[0]) - se.doclist[1].item_code = "_Test Serialized Item With Series" - se.doclist[1].qty = 2 - se.doclist[1].transfer_qty = 2 + se.get("mtn_details")[0].item_code = "_Test Serialized Item With Series" + se.get("mtn_details")[0].qty = 2 + se.get("mtn_details")[0].transfer_qty = 2 se.insert() se.submit() return se -test_records = frappe.get_test_records('Stock Entry') \ No newline at end of file +test_records = frappe.get_test_records('Stock Entry') diff --git a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py index 083879de53..c1ffd02b51 100644 --- a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py +++ b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py @@ -228,9 +228,9 @@ class TestStockReconciliation(unittest.TestCase): pr1 = frappe.copy_doc(stock_entry) pr1.posting_date = "2012-12-15" pr1.posting_time = "02:00" - pr1.doclist[1].qty = 10 - pr1.doclist[1].transfer_qty = 10 - pr1.doclist[1].incoming_rate = 700 + pr1.get("mtn_details")[0].qty = 10 + pr1.get("mtn_details")[0].transfer_qty = 10 + pr1.get("mtn_details")[0].incoming_rate = 700 pr1.insert() pr1.submit() @@ -238,11 +238,11 @@ class TestStockReconciliation(unittest.TestCase): pr2.posting_date = "2012-12-25" pr2.posting_time = "03:00" pr2.purpose = "Material Issue" - pr2.doclist[1].s_warehouse = "_Test Warehouse - _TC" - pr2.doclist[1].t_warehouse = None - pr2.doclist[1].qty = 15 - pr2.doclist[1].transfer_qty = 15 - pr2.doclist[1].incoming_rate = 0 + pr2.get("mtn_details")[0].s_warehouse = "_Test Warehouse - _TC" + pr2.get("mtn_details")[0].t_warehouse = None + pr2.get("mtn_details")[0].qty = 15 + pr2.get("mtn_details")[0].transfer_qty = 15 + pr2.get("mtn_details")[0].incoming_rate = 0 pr2.insert() pr2.submit() @@ -250,11 +250,11 @@ class TestStockReconciliation(unittest.TestCase): pr3.posting_date = "2012-12-31" pr3.posting_time = "08:00" pr3.purpose = "Material Issue" - pr3.doclist[1].s_warehouse = "_Test Warehouse - _TC" - pr3.doclist[1].t_warehouse = None - pr3.doclist[1].qty = 20 - pr3.doclist[1].transfer_qty = 20 - pr3.doclist[1].incoming_rate = 0 + pr3.get("mtn_details")[0].s_warehouse = "_Test Warehouse - _TC" + pr3.get("mtn_details")[0].t_warehouse = None + pr3.get("mtn_details")[0].qty = 20 + pr3.get("mtn_details")[0].transfer_qty = 20 + pr3.get("mtn_details")[0].incoming_rate = 0 pr3.insert() pr3.submit() @@ -263,9 +263,9 @@ class TestStockReconciliation(unittest.TestCase): pr4.posting_date = "2013-01-05" pr4.fiscal_year = "_Test Fiscal Year 2013" pr4.posting_time = "07:00" - pr4.doclist[1].qty = 15 - pr4.doclist[1].transfer_qty = 15 - pr4.doclist[1].incoming_rate = 1200 + pr4.get("mtn_details")[0].qty = 15 + pr4.get("mtn_details")[0].transfer_qty = 15 + pr4.get("mtn_details")[0].incoming_rate = 1200 pr4.insert() pr4.submit() diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py index cf95845cc8..8a19bb19a7 100644 --- a/erpnext/stock/stock_ledger.py +++ b/erpnext/stock/stock_ledger.py @@ -17,36 +17,35 @@ _exceptions = frappe.local('stockledger_exceptions') def make_sl_entries(sl_entries, is_amended=None): if sl_entries: from erpnext.stock.utils import update_bin - + cancel = True if sl_entries[0].get("is_cancelled") == "Yes" else False if cancel: set_as_cancel(sl_entries[0].get('voucher_no'), sl_entries[0].get('voucher_type')) - + for sle in sl_entries: sle_id = None if sle.get('is_cancelled') == 'Yes': sle['actual_qty'] = -flt(sle['actual_qty']) - + if sle.get("actual_qty"): sle_id = make_entry(sle) - + args = sle.copy() args.update({ "sle_id": sle_id, "is_amended": is_amended }) update_bin(args) - if cancel: - delete_cancelled_entry(sl_entries[0].get('voucher_type'), + delete_cancelled_entry(sl_entries[0].get('voucher_type'), sl_entries[0].get('voucher_no')) - + def set_as_cancel(voucher_type, voucher_no): frappe.db.sql("""update `tabStock Ledger Entry` set is_cancelled='Yes', modified=%s, modified_by=%s - where voucher_no=%s and voucher_type=%s""", + where voucher_no=%s and voucher_type=%s""", (now(), frappe.session.user, voucher_type, voucher_no)) - + def make_entry(args): args.update({"doctype": "Stock Ledger Entry"}) sle = frappe.get_doc(args) @@ -54,16 +53,16 @@ def make_entry(args): sle.insert() sle.submit() return sle.name - + def delete_cancelled_entry(voucher_type, voucher_no): - frappe.db.sql("""delete from `tabStock Ledger Entry` + frappe.db.sql("""delete from `tabStock Ledger Entry` where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no)) def update_entries_after(args, verbose=1): """ - update valution rate and qty after transaction + update valution rate and qty after transaction from the current time-bucket onwards - + args = { "item_code": "ABC", "warehouse": "XYZ", @@ -73,15 +72,15 @@ def update_entries_after(args, verbose=1): """ if not _exceptions: frappe.local.stockledger_exceptions = [] - + previous_sle = get_sle_before_datetime(args) - + qty_after_transaction = flt(previous_sle.get("qty_after_transaction")) valuation_rate = flt(previous_sle.get("valuation_rate")) stock_queue = json.loads(previous_sle.get("stock_queue") or "[]") stock_value = flt(previous_sle.get("stock_value")) prev_stock_value = flt(previous_sle.get("stock_value")) - + entries_to_fix = get_sle_after_datetime(previous_sle or \ {"item_code": args["item_code"], "warehouse": args["warehouse"]}, for_update=True) @@ -90,7 +89,7 @@ def update_entries_after(args, verbose=1): for sle in entries_to_fix: if sle.serial_no or not cint(frappe.db.get_default("allow_negative_stock")): - # validate negative stock for serialized items, fifo valuation + # validate negative stock for serialized items, fifo valuation # or when negative stock is not allowed for moving average if not validate_negative_stock(qty_after_transaction, sle): qty_after_transaction += flt(sle.actual_qty) @@ -102,9 +101,9 @@ def update_entries_after(args, verbose=1): valuation_rate = get_moving_average_values(qty_after_transaction, sle, valuation_rate) else: valuation_rate = get_fifo_values(qty_after_transaction, sle, stock_queue) - + qty_after_transaction += flt(sle.actual_qty) - + # get stock value if sle.serial_no: stock_value = qty_after_transaction * valuation_rate @@ -113,29 +112,29 @@ def update_entries_after(args, verbose=1): (qty_after_transaction * valuation_rate) or 0 else: stock_value = sum((flt(batch[0]) * flt(batch[1]) for batch in stock_queue)) - + # rounding as per precision from frappe.model.meta import get_field_precision meta = frappe.get_meta("Stock Ledger Entry") - - stock_value = flt(stock_value, get_field_precision(meta.get_field("stock_value"), + + stock_value = flt(stock_value, get_field_precision(meta.get_field("stock_value"), frappe._dict({"fields": sle}))) - + stock_value_difference = stock_value - prev_stock_value prev_stock_value = stock_value - + # update current sle frappe.db.sql("""update `tabStock Ledger Entry` set qty_after_transaction=%s, valuation_rate=%s, stock_queue=%s, - stock_value=%s, stock_value_difference=%s where name=%s""", + stock_value=%s, stock_value_difference=%s where name=%s""", (qty_after_transaction, valuation_rate, json.dumps(stock_queue), stock_value, stock_value_difference, sle.name)) - + if _exceptions: _raise_exceptions(args, verbose) - + # update bin - if not frappe.db.exists({"doctype": "Bin", "item_code": args["item_code"], + if not frappe.db.exists({"doctype": "Bin", "item_code": args["item_code"], "warehouse": args["warehouse"]}): bin_wrapper = frappe.get_doc({ "doctype": "Bin", @@ -144,13 +143,13 @@ def update_entries_after(args, verbose=1): }) bin_wrapper.ignore_permissions = 1 bin_wrapper.insert() - + frappe.db.sql("""update `tabBin` set valuation_rate=%s, actual_qty=%s, - stock_value=%s, + stock_value=%s, projected_qty = (actual_qty + indented_qty + ordered_qty + planned_qty - reserved_qty) where item_code=%s and warehouse=%s""", (valuation_rate, qty_after_transaction, stock_value, args["item_code"], args["warehouse"])) - + def get_sle_before_datetime(args, for_update=False): """ get previous stock ledger entry before current time-bucket @@ -164,23 +163,23 @@ def get_sle_before_datetime(args, for_update=False): sle = get_stock_ledger_entries(args, ["timestamp(posting_date, posting_time) < timestamp(%(posting_date)s, %(posting_time)s)"], "desc", "limit 1", for_update=for_update) - + return sle and sle[0] or frappe._dict() - + def get_sle_after_datetime(args, for_update=False): """get Stock Ledger Entries after a particular datetime, for reposting""" - # NOTE: using for update of + # NOTE: using for update of return get_stock_ledger_entries(args, ["timestamp(posting_date, posting_time) > timestamp(%(posting_date)s, %(posting_time)s)"], "asc", for_update=for_update) - + def get_stock_ledger_entries(args, conditions=None, order="desc", limit=None, for_update=False): """get stock ledger entries filtered by specific posting datetime conditions""" if not args.get("posting_date"): args["posting_date"] = "1900-01-01" if not args.get("posting_time"): args["posting_time"] = "00:00" - + return frappe.db.sql("""select * from `tabStock Ledger Entry` where item_code = %%(item_code)s and warehouse = %%(warehouse)s @@ -193,7 +192,7 @@ def get_stock_ledger_entries(args, conditions=None, order="desc", limit=None, fo "for_update": for_update and "for update" or "", "order": order }, args, as_dict=1) - + def validate_negative_stock(qty_after_transaction, sle): """ validate negative stock for entries current datetime onwards @@ -203,7 +202,7 @@ def validate_negative_stock(qty_after_transaction, sle): if not _exceptions: frappe.local.stockledger_exceptions = [] - + if diff < 0 and abs(diff) > 0.0001: # negative stock! exc = sle.copy().update({"diff": diff}) @@ -211,12 +210,12 @@ def validate_negative_stock(qty_after_transaction, sle): return False else: return True - + def get_serialized_values(qty_after_transaction, sle, valuation_rate): incoming_rate = flt(sle.incoming_rate) actual_qty = flt(sle.actual_qty) serial_no = cstr(sle.serial_no).split("\n") - + if incoming_rate < 0: # wrong incoming rate incoming_rate = valuation_rate @@ -226,7 +225,7 @@ def get_serialized_values(qty_after_transaction, sle, valuation_rate): incoming_rate = flt(frappe.db.sql("""select avg(ifnull(purchase_rate, 0)) from `tabSerial No` where name in (%s)""" % (", ".join(["%s"]*len(serial_no))), tuple(serial_no))[0][0]) - + if incoming_rate and not valuation_rate: valuation_rate = incoming_rate else: @@ -237,33 +236,33 @@ def get_serialized_values(qty_after_transaction, sle, valuation_rate): # calculate new valuation rate only if stock value is positive # else it remains the same as that of previous entry valuation_rate = new_stock_value / new_stock_qty - + return valuation_rate - + def get_moving_average_values(qty_after_transaction, sle, valuation_rate): incoming_rate = flt(sle.incoming_rate) - actual_qty = flt(sle.actual_qty) - + actual_qty = flt(sle.actual_qty) + if not incoming_rate: # In case of delivery/stock issue in_rate = 0 or wrong incoming rate incoming_rate = valuation_rate - + elif qty_after_transaction < 0: # if negative stock, take current valuation rate as incoming rate valuation_rate = incoming_rate - + new_stock_qty = qty_after_transaction + actual_qty new_stock_value = qty_after_transaction * valuation_rate + actual_qty * incoming_rate - + if new_stock_qty > 0 and new_stock_value > 0: valuation_rate = new_stock_value / flt(new_stock_qty) elif new_stock_qty <= 0: valuation_rate = 0.0 - + # NOTE: val_rate is same as previous entry if new stock value is negative - + return valuation_rate - + def get_fifo_values(qty_after_transaction, sle, stock_queue): incoming_rate = flt(sle.incoming_rate) actual_qty = flt(sle.actual_qty) @@ -282,9 +281,9 @@ def get_fifo_values(qty_after_transaction, sle, stock_queue): while qty_to_pop: if not stock_queue: stock_queue.append([0, 0]) - + batch = stock_queue[0] - + if 0 < batch[0] <= qty_to_pop: # if batch qty > 0 # not enough or exactly same qty in current batch, clear batch @@ -296,7 +295,7 @@ def get_fifo_values(qty_after_transaction, sle, stock_queue): incoming_cost += flt(qty_to_pop) * flt(batch[1]) batch[0] -= qty_to_pop qty_to_pop = 0 - + stock_value = sum((flt(batch[0]) * flt(batch[1]) for batch in stock_queue)) stock_qty = sum((flt(batch[0]) for batch in stock_queue)) @@ -306,9 +305,9 @@ def get_fifo_values(qty_after_transaction, sle, stock_queue): def _raise_exceptions(args, verbose=1): deficiency = min(e["diff"] for e in _exceptions) - msg = """Negative stock error: + msg = """Negative stock error: Cannot complete this transaction because stock will start - becoming negative (%s) for Item %s in Warehouse + becoming negative (%s) for Item %s in Warehouse %s on %s %s in Transaction %s %s. Total Quantity Deficiency: %s""" % \ (_exceptions[0]["diff"], args.get("item_code"), args.get("warehouse"), @@ -319,13 +318,13 @@ def _raise_exceptions(args, verbose=1): msgprint(msg, raise_exception=NegativeStockError) else: raise NegativeStockError, msg - + def get_previous_sle(args, for_update=False): """ - get the last sle on or before the current time-bucket, + get the last sle on or before the current time-bucket, to get actual qty before transaction, this function is called from various transaction like stock entry, reco etc - + args = { "item_code": "ABC", "warehouse": "XYZ", @@ -335,7 +334,7 @@ def get_previous_sle(args, for_update=False): } """ if not args.get("sle"): args["sle"] = "" - + sle = get_stock_ledger_entries(args, ["name != %(sle)s", "timestamp(posting_date, posting_time) <= timestamp(%(posting_date)s, %(posting_time)s)"], "desc", "limit 1", for_update=for_update)