diff --git a/erpnext/accounts/doctype/asset/asset.py b/erpnext/accounts/doctype/asset/asset.py index b8d0ec8170a..a99a8cff063 100644 --- a/erpnext/accounts/doctype/asset/asset.py +++ b/erpnext/accounts/doctype/asset/asset.py @@ -32,7 +32,7 @@ class Asset(Document): self.set_status() def validate_item(self): - item = frappe.db.get_value("Item", self.item_code, + item = frappe.db.get_value("Item", self.item_code, ["is_fixed_asset", "is_stock_item", "disabled"], as_dict=1) if not item: frappe.throw(_("Item {0} does not exist").format(self.item_code)) @@ -42,7 +42,7 @@ class Asset(Document): frappe.throw(_("Item {0} must be a Fixed Asset Item").format(self.item_code)) elif item.is_stock_item: frappe.throw(_("Item {0} must be a non-stock item").format(self.item_code)) - + def set_missing_values(self): if self.item_code: item_details = get_item_details(self.item_code) @@ -50,7 +50,7 @@ class Asset(Document): if not self.get(field): self.set(field, value) - self.value_after_depreciation = (flt(self.gross_purchase_amount) - + self.value_after_depreciation = (flt(self.gross_purchase_amount) - flt(self.opening_accumulated_depreciation)) def validate_asset_values(self): @@ -59,7 +59,7 @@ class Asset(Document): if not flt(self.gross_purchase_amount): frappe.throw(_("Gross Purchase Amount is mandatory"), frappe.MandatoryError) - + if not self.is_existing_asset: self.opening_accumulated_depreciation = 0 self.number_of_depreciations_booked = 0 @@ -70,33 +70,33 @@ class Asset(Document): if flt(self.opening_accumulated_depreciation) > depreciable_amount: frappe.throw(_("Opening Accumulated Depreciation must be less than equal to {0}") .format(depreciable_amount)) - + if self.opening_accumulated_depreciation: if not self.number_of_depreciations_booked: frappe.throw(_("Please set Number of Depreciations Booked")) else: self.number_of_depreciations_booked = 0 - + if cint(self.number_of_depreciations_booked) > cint(self.total_number_of_depreciations): frappe.throw(_("Number of Depreciations Booked cannot be greater than Total Number of Depreciations")) - + if self.next_depreciation_date and getdate(self.next_depreciation_date) < getdate(nowdate()): frappe.msgprint(_("Next Depreciation Date is entered as past date"), title=_('Warning'), indicator='red') - + if self.next_depreciation_date and getdate(self.next_depreciation_date) < getdate(self.purchase_date): frappe.throw(_("Next Depreciation Date cannot be before Purchase Date")) - - if (flt(self.value_after_depreciation) > flt(self.expected_value_after_useful_life) + + if (flt(self.value_after_depreciation) > flt(self.expected_value_after_useful_life) and not self.next_depreciation_date): frappe.throw(_("Please set Next Depreciation Date")) def make_depreciation_schedule(self): if self.depreciation_method != 'Manual': self.schedules = [] - + if not self.get("schedules") and self.next_depreciation_date: value_after_depreciation = flt(self.value_after_depreciation) - + number_of_pending_depreciations = cint(self.total_number_of_depreciations) - \ cint(self.number_of_depreciations_booked) if number_of_pending_depreciations: @@ -111,7 +111,7 @@ class Asset(Document): "schedule_date": schedule_date, "depreciation_amount": depreciation_amount }) - + def set_accumulated_depreciation(self): accumulated_depreciation = flt(self.opening_accumulated_depreciation) for d in self.get("schedules"): @@ -121,7 +121,7 @@ class Asset(Document): def get_depreciation_amount(self, depreciable_value): if self.depreciation_method in ("Straight Line", "Manual"): depreciation_amount = (flt(self.value_after_depreciation) - - flt(self.expected_value_after_useful_life)) / (cint(self.total_number_of_depreciations) - + flt(self.expected_value_after_useful_life)) / (cint(self.total_number_of_depreciations) - cint(self.number_of_depreciations_booked)) else: factor = 200.0 / self.total_number_of_depreciations @@ -132,14 +132,14 @@ class Asset(Document): depreciation_amount = flt(depreciable_value) - flt(self.expected_value_after_useful_life) return depreciation_amount - + def validate_expected_value_after_useful_life(self): accumulated_depreciation_after_full_schedule = \ max([d.accumulated_depreciation_amount for d in self.get("schedules")]) - - asset_value_after_full_schedule = (flt(self.gross_purchase_amount) - + + asset_value_after_full_schedule = (flt(self.gross_purchase_amount) - flt(accumulated_depreciation_after_full_schedule)) - + if self.expected_value_after_useful_life < asset_value_after_full_schedule: frappe.throw(_("Expected value after useful life must be greater than or equal to {0}") .format(asset_value_after_full_schedule)) @@ -156,8 +156,8 @@ class Asset(Document): if d.journal_entry: frappe.get_doc("Journal Entry", d.journal_entry).cancel() d.db_set("journal_entry", None) - - self.db_set("value_after_depreciation", + + self.db_set("value_after_depreciation", (flt(self.gross_purchase_amount) - flt(self.opening_accumulated_depreciation))) def set_status(self, status=None): @@ -188,6 +188,7 @@ def make_purchase_invoice(asset, item_code, gross_purchase_amount, company, post pi = frappe.new_doc("Purchase Invoice") pi.company = company pi.currency = frappe.db.get_value("Company", company, "default_currency") + pi.set_posting_date = 1 pi.posting_date = posting_date pi.append("items", { "item_code": item_code, @@ -200,7 +201,7 @@ def make_purchase_invoice(asset, item_code, gross_purchase_amount, company, post }) pi.set_missing_values() return pi - + @frappe.whitelist() def make_sales_invoice(asset, item_code, company): si = frappe.new_doc("Sales Invoice") @@ -217,7 +218,7 @@ def make_sales_invoice(asset, item_code, company): }) si.set_missing_values() return si - + @frappe.whitelist() def transfer_asset(args): import json @@ -226,23 +227,23 @@ def transfer_asset(args): movement_entry.update(args) movement_entry.insert() movement_entry.submit() - + frappe.db.commit() - + frappe.msgprint(_("Asset Movement record {0} created").format("{0}".format(movement_entry.name))) - + @frappe.whitelist() def get_item_details(item_code): asset_category = frappe.db.get_value("Item", item_code, "asset_category") - + if not asset_category: frappe.throw(_("Please enter Asset Category in Item {0}").format(item_code)) - - ret = frappe.db.get_value("Asset Category", asset_category, + + ret = frappe.db.get_value("Asset Category", asset_category, ["depreciation_method", "total_number_of_depreciations", "frequency_of_depreciation"], as_dict=1) - + ret.update({ "asset_category": asset_category }) - + return ret diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.json b/erpnext/accounts/doctype/payment_entry/payment_entry.json index e744a3cf356..7fac377c026 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.json +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_guest_to_view": 0, "allow_import": 1, "allow_rename": 0, "autoname": "naming_series:", @@ -254,7 +255,7 @@ "collapsible": 0, "columns": 0, "default": "", - "depends_on": "eval:in_list([\"Receive\", \"Pay\"], doc.payment_type)", + "depends_on": "eval:in_list([\"Receive\", \"Pay\"], doc.payment_type) && doc.docstatus==0", "fieldname": "party_type", "fieldtype": "Link", "hidden": 0, @@ -1664,17 +1665,17 @@ "unique": 0 } ], + "has_web_view": 0, "hide_heading": 0, "hide_toolbar": 0, "idx": 0, "image_view": 0, "in_create": 0, - "in_dialog": 0, "is_submittable": 1, "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2017-02-17 16:15:52.917533", + "modified": "2017-03-14 17:12:48.816644", "modified_by": "Administrator", "module": "Accounts", "name": "Payment Entry", diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index f3d311b56d9..cb4a0875aeb 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -1046,6 +1046,8 @@ class TestSalesInvoice(unittest.TestCase): def create_sales_invoice(**args): si = frappe.new_doc("Sales Invoice") args = frappe._dict(args) + if si.posting_date: + si.set_posting_date = 1 si.posting_date = args.posting_date or nowdate() si.company = args.company or "_Test Company" diff --git a/erpnext/controllers/recurring_document.py b/erpnext/controllers/recurring_document.py index a0367608d26..713e9bac2f1 100644 --- a/erpnext/controllers/recurring_document.py +++ b/erpnext/controllers/recurring_document.py @@ -93,6 +93,9 @@ def make_new_document(reference_doc, date_field, posting_date): "next_date": get_next_date(reference_doc.next_date, mcount,cint(reference_doc.repeat_on_day_of_month)) }) + if new_document.meta.get_field('set_posting_time'): + new_document.set('set_posting_time', 1) + # copy document fields for fieldname in ("owner", "recurring_type", "repeat_on_day_of_month", "recurring_id", "notification_email_address", "is_recurring", "end_date", diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py index f10b981d73c..fce11dce51e 100644 --- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py @@ -328,7 +328,7 @@ class TestDeliveryNote(unittest.TestCase): def test_delivery_of_bundled_items_to_target_warehouse(self): set_perpetual_inventory() - + set_valuation_method("_Test Item", "FIFO") set_valuation_method("_Test Item Home Desktop 100", "FIFO") @@ -337,7 +337,7 @@ class TestDeliveryNote(unittest.TestCase): qty=100, rate=100) create_stock_reconciliation(item_code="_Test Item Home Desktop 100", target=warehouse, qty=100, rate=100) - + opening_qty_test_warehouse_1 = get_qty_after_transaction(warehouse="_Test Warehouse 1 - _TC") dn = create_delivery_note(item_code="_Test Product Bundle Item", @@ -354,28 +354,28 @@ class TestDeliveryNote(unittest.TestCase): # 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, + stock_value_difference = frappe.db.get_value("Stock Ledger Entry", + {"voucher_type": "Delivery Note", "voucher_no": dn.name, "item_code": "_Test Item", "warehouse": "_Test Warehouse - _TC"}, "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, + stock_value_difference1 = frappe.db.get_value("Stock Ledger Entry", + {"voucher_type": "Delivery Note", "voucher_no": dn.name, "item_code": "_Test Item", "warehouse": "_Test Warehouse 1 - _TC"}, "stock_value_difference") self.assertEquals(abs(stock_value_difference), stock_value_difference1) # for "_Test Item Home Desktop 100" - stock_value_difference = frappe.db.get_value("Stock Ledger Entry", - {"voucher_type": "Delivery Note", "voucher_no": dn.name, + stock_value_difference = frappe.db.get_value("Stock Ledger Entry", + {"voucher_type": "Delivery Note", "voucher_no": dn.name, "item_code": "_Test Item Home Desktop 100", "warehouse": "_Test Warehouse - _TC"}, "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, + stock_value_difference1 = frappe.db.get_value("Stock Ledger Entry", + {"voucher_type": "Delivery Note", "voucher_no": dn.name, "item_code": "_Test Item Home Desktop 100", "warehouse": "_Test Warehouse 1 - _TC"}, "stock_value_difference") @@ -397,118 +397,120 @@ class TestDeliveryNote(unittest.TestCase): self.assertEquals([gle.debit, gle.credit], expected_values.get(gle.account)) set_perpetual_inventory(0) - + def test_closed_delivery_note(self): from erpnext.stock.doctype.delivery_note.delivery_note import update_delivery_note_status - + dn = create_delivery_note(do_not_submit=True) dn.submit() - + update_delivery_note_status(dn.name, "Closed") self.assertEquals(frappe.db.get_value("Delivery Note", dn.name, "Status"), "Closed") - + def test_dn_billing_status_case1(self): # SO -> DN -> SI so = make_sales_order() dn = create_dn_against_so(so.name, delivered_qty=2) - + self.assertEqual(dn.status, "To Bill") self.assertEqual(dn.per_billed, 0) - + si = make_sales_invoice(dn.name) si.submit() - + dn.load_from_db() self.assertEqual(dn.get("items")[0].billed_amt, 200) self.assertEqual(dn.per_billed, 100) self.assertEqual(dn.status, "Completed") - + def test_dn_billing_status_case2(self): # SO -> SI and SO -> DN1, DN2 from erpnext.selling.doctype.sales_order.sales_order import make_delivery_note, make_sales_invoice - + so = make_sales_order() - + si = make_sales_invoice(so.name) si.get("items")[0].qty = 5 si.insert() si.submit() - + frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1) - + dn1 = make_delivery_note(so.name) + dn1.set_posting_time = 1 dn1.posting_time = "10:00" dn1.get("items")[0].qty = 2 dn1.submit() - + self.assertEqual(dn1.get("items")[0].billed_amt, 200) self.assertEqual(dn1.per_billed, 100) self.assertEqual(dn1.status, "Completed") - + dn2 = make_delivery_note(so.name) dn2.posting_time = "08:00" dn2.get("items")[0].qty = 4 dn2.submit() - + dn1.load_from_db() self.assertEqual(dn1.get("items")[0].billed_amt, 100) self.assertEqual(dn1.per_billed, 50) self.assertEqual(dn1.status, "To Bill") - + self.assertEqual(dn2.get("items")[0].billed_amt, 400) self.assertEqual(dn2.per_billed, 100) self.assertEqual(dn2.status, "Completed") - + def test_dn_billing_status_case3(self): # SO -> DN1 -> SI and SO -> SI and SO -> DN2 from erpnext.selling.doctype.sales_order.sales_order \ import make_delivery_note, make_sales_invoice as make_sales_invoice_from_so frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1) - + so = make_sales_order() - + dn1 = make_delivery_note(so.name) + dn1.set_posting_time = 1 dn1.posting_time = "10:00" dn1.get("items")[0].qty = 2 dn1.submit() si1 = make_sales_invoice(dn1.name) si1.submit() - + dn1.load_from_db() self.assertEqual(dn1.per_billed, 100) - + si2 = make_sales_invoice_from_so(so.name) si2.get("items")[0].qty = 4 si2.submit() - + dn2 = make_delivery_note(so.name) dn2.posting_time = "08:00" dn2.get("items")[0].qty = 5 dn2.submit() - + dn1.load_from_db() self.assertEqual(dn1.get("items")[0].billed_amt, 200) self.assertEqual(dn1.per_billed, 100) self.assertEqual(dn1.status, "Completed") - + self.assertEqual(dn2.get("items")[0].billed_amt, 400) self.assertEqual(dn2.per_billed, 80) self.assertEqual(dn2.status, "To Bill") - + def test_dn_billing_status_case4(self): # SO -> SI -> DN from erpnext.selling.doctype.sales_order.sales_order import make_sales_invoice from erpnext.accounts.doctype.sales_invoice.sales_invoice import make_delivery_note - + so = make_sales_order() - + si = make_sales_invoice(so.name) si.submit() - + dn = make_delivery_note(si.name) dn.submit() - + self.assertEqual(dn.get("items")[0].billed_amt, 1000) self.assertEqual(dn.per_billed, 100) self.assertEqual(dn.status, "Completed") diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py index 30f2a061527..79df591349a 100644 --- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py @@ -79,10 +79,10 @@ class TestStockEntry(unittest.TestCase): def test_auto_material_request_for_variant(self): self._test_auto_material_request("_Test Variant Item-S") - + def test_auto_material_request_for_warehouse_group(self): self._test_auto_material_request("_Test Item Warehouse Group Wise Reorder", warehouse="_Test Warehouse Group-C1 - _TC") - + def _test_auto_material_request(self, item_code, material_request_type="Purchase", warehouse="_Test Warehouse - _TC"): item = frappe.get_doc("Item", item_code) @@ -126,7 +126,7 @@ class TestStockEntry(unittest.TestCase): mr = make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, basic_rate=100, expense_account="Stock Adjustment - _TC") - + stock_in_hand_account = frappe.db.get_value("Account", {"account_type": "Stock", "warehouse": mr.get("items")[0].t_warehouse}) @@ -154,7 +154,7 @@ class TestStockEntry(unittest.TestCase): make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, basic_rate=100, expense_account="Stock Adjustment - _TC") - mi = make_stock_entry(item_code="_Test Item", source="_Test Warehouse - _TC", + mi = make_stock_entry(item_code="_Test Item", source="_Test Warehouse - _TC", qty=40, expense_account="Stock Adjustment - _TC") self.check_stock_ledger_entries("Stock Entry", mi.name, @@ -512,6 +512,7 @@ class TestStockEntry(unittest.TestCase): # test freeze_stocks_upto_days frappe.db.set_value("Stock Settings", None, "stock_frozen_upto_days", 7) se = frappe.copy_doc(test_records[0]) + se.set_posting_time = 1 se.posting_date = add_days(nowdate(), -15) se.insert() self.assertRaises(StockFreezeError, se.submit) diff --git a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py index f9629a1ff22..212bb51185d 100644 --- a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py +++ b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py @@ -37,7 +37,7 @@ class TestStockReconciliation(unittest.TestCase): for d in input_data: set_valuation_method("_Test Item", valuation_method) - + last_sle = get_previous_sle({ "item_code": "_Test Item", "warehouse": "_Test Warehouse - _TC", @@ -96,6 +96,7 @@ def create_stock_reconciliation(**args): sr = frappe.new_doc("Stock Reconciliation") sr.posting_date = args.posting_date or nowdate() sr.posting_time = args.posting_time or nowtime() + sr.set_posting_time = 1 sr.company = args.company or "_Test Company" sr.expense_account = args.expense_account or \ ("Stock Adjustment - _TC" if frappe.get_all("Stock Ledger Entry") else "Temporary Opening - _TC")