diff --git a/erpnext/accounts/doctype/journal_entry/test_journal_entry.py b/erpnext/accounts/doctype/journal_entry/test_journal_entry.py index c70f10df631..8995e34220f 100644 --- a/erpnext/accounts/doctype/journal_entry/test_journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/test_journal_entry.py @@ -69,8 +69,8 @@ class TestJournalEntry(unittest.TestCase): if test_voucher.doctype == "Journal Entry": # if test_voucher is a Journal Entry, test cancellation of test_voucher test_voucher.cancel() - self.assertTrue(not frappe.db.sql("""select name from `tabJournal Entry Account` - where against_jv=%s""", test_voucher.name)) + self.assertFalse(frappe.db.sql("""select name from `tabJournal Entry Account` + where reference_type='Journal Entry' and reference_name=%s""", test_voucher.name)) elif test_voucher.doctype in ["Sales Order", "Purchase Order"]: # if test_voucher is a Sales Order/Purchase Order, test error on cancellation of test_voucher diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index 5f3d4c8a042..d12b2d7ca91 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -218,23 +218,20 @@ class TestPurchaseInvoice(unittest.TestCase): pi.load_from_db() self.assertTrue(frappe.db.sql("""select name from `tabJournal Entry Account` - where against_voucher=%s""", pi.name)) - - self.assertTrue(frappe.db.sql("""select name from `tabJournal Entry Account` - where against_voucher=%s and debit=300""", pi.name)) + where reference_type='Purchase Invoice' and reference_name=%s and debit=300""", pi.name)) self.assertEqual(pi.outstanding_amount, 1212.30) pi.cancel() - self.assertTrue(not frappe.db.sql("""select name from `tabJournal Entry Account` - where against_voucher=%s""", pi.name)) + self.assertFalse(frappe.db.sql("""select name from `tabJournal Entry Account` + where reference_type='Purchase Invoice' and reference_name=%s""", pi.name)) def test_recurring_invoice(self): from erpnext.controllers.tests.test_recurring_document import test_recurring_document test_recurring_document(self, test_records) - - def test_total_purchase_cost_for_project(self): + + def test_total_purchase_cost_for_project(self): purchase_invoice = frappe.new_doc('Purchase Invoice') purchase_invoice.update({ "credit_to": "_Test Payable - _TC", @@ -260,29 +257,29 @@ class TestPurchaseInvoice(unittest.TestCase): ] }) purchase_invoice.save() - purchase_invoice.submit() + purchase_invoice.submit() self.assertEqual(frappe.db.get_value("Project", "_Test Project", "total_purchase_cost"), 2000) - + purchase_invoice1 = frappe.copy_doc(purchase_invoice) purchase_invoice1.save() purchase_invoice1.submit() - + self.assertEqual(frappe.db.get_value("Project", "_Test Project", "total_purchase_cost"), 4000) - - purchase_invoice1.cancel() + + purchase_invoice1.cancel() self.assertEqual(frappe.db.get_value("Project", "_Test Project", "total_purchase_cost"), 2000) - - purchase_invoice.cancel() + + purchase_invoice.cancel() self.assertEqual(frappe.db.get_value("Project", "_Test Project", "total_purchase_cost"), 0) - + def test_return_purchase_invoice(self): set_perpetual_inventory() - + pi = make_purchase_invoice() - + return_pi = make_purchase_invoice(is_return=1, return_against=pi.name, qty=-2) - - + + # check gl entries for return gl_entries = frappe.db.sql("""select account, debit, credit from `tabGL Entry` where voucher_type=%s and voucher_no=%s @@ -298,9 +295,9 @@ class TestPurchaseInvoice(unittest.TestCase): for gle in gl_entries: self.assertEquals(expected_values[gle.account][0], gle.debit) self.assertEquals(expected_values[gle.account][1], gle.credit) - + set_perpetual_inventory(0) - + def make_purchase_invoice(**args): pi = frappe.new_doc("Purchase Invoice") args = frappe._dict(args) @@ -313,7 +310,7 @@ def make_purchase_invoice(**args): pi.currency = args.currency or "INR" pi.is_return = args.is_return pi.return_against = args.return_against - + pi.append("items", { "item_code": args.item or args.item_code or "_Test Item", "warehouse": args.warehouse or "_Test Warehouse - _TC", diff --git a/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.py b/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.py index ab6bbab3fa4..3fabae0e075 100644 --- a/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.py +++ b/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.py @@ -4,6 +4,14 @@ from __future__ import unicode_literals import frappe from frappe.model.document import Document +from frappe.utils import cint +from dateutil.relativedelta import relativedelta class ManufacturingSettings(Document): pass + +def get_mins_between_operations(): + if not hasattr(frappe.local, "_mins_between_operations"): + frappe.local._mins_between_operations = cint(frappe.db.get_single_value("Manufacturing Settings", + "mins_between_operations")) or 10 + return relativedelta(minutes=frappe.local._mins_between_operations) diff --git a/erpnext/manufacturing/doctype/production_order/production_order.py b/erpnext/manufacturing/doctype/production_order/production_order.py index 023c43eac49..b6befe08673 100644 --- a/erpnext/manufacturing/doctype/production_order/production_order.py +++ b/erpnext/manufacturing/doctype/production_order/production_order.py @@ -13,6 +13,7 @@ from erpnext.stock.doctype.item.item import validate_end_of_life from erpnext.manufacturing.doctype.workstation.workstation import WorkstationHolidayError, NotInWorkingHoursError from erpnext.projects.doctype.time_log.time_log import OverlapError from erpnext.stock.doctype.stock_entry.stock_entry import get_additional_costs +from erpnext.manufacturing.doctype.manufacturing_settings.manufacturing_settings import get_mins_between_operations class OverProductionError(frappe.ValidationError): pass class StockOverProductionError(frappe.ValidationError): pass @@ -231,6 +232,7 @@ class ProductionOrder(Document): original_start_time = time_log.from_time while True: _from_time = time_log.from_time + try: time_log.save() break @@ -248,6 +250,7 @@ class ProductionOrder(Document): frappe.msgprint(_("Unable to find Time Slot in the next {0} days for Operation {1}").format(plan_days, d.operation)) break + # if time log needs to be moved, make sure that the from time is not the same if _from_time == time_log.from_time: frappe.throw("Capacity Planning Error") @@ -273,19 +276,13 @@ class ProductionOrder(Document): d.planned_start_time = self.planned_start_date else: d.planned_start_time = get_datetime(self.operations[i-1].planned_end_time)\ - + self.get_mins_between_operations() + + get_mins_between_operations() d.planned_end_time = get_datetime(d.planned_start_time) + relativedelta(minutes = d.time_in_mins) if d.planned_start_time == d.planned_end_time: frappe.throw(_("Capacity Planning Error")) - def get_mins_between_operations(self): - if not hasattr(self, "_mins_between_operations"): - self._mins_between_operations = cint(frappe.db.get_single_value("Manufacturing Settings", - "mins_between_operations")) or 10 - return relativedelta(minutes=self._mins_between_operations) - def check_operation_fits_in_working_hours(self, d): """Raises expection if operation is longer than working hours in the given workstation.""" from erpnext.manufacturing.doctype.workstation.workstation import check_if_within_operating_hours diff --git a/erpnext/projects/doctype/time_log/time_log.py b/erpnext/projects/doctype/time_log/time_log.py index 0f50e9cc5aa..6e937c09e75 100644 --- a/erpnext/projects/doctype/time_log/time_log.py +++ b/erpnext/projects/doctype/time_log/time_log.py @@ -6,6 +6,7 @@ import frappe, json from frappe import _ from frappe.utils import cstr, flt, get_datetime, get_time, getdate from dateutil.relativedelta import relativedelta +from erpnext.manufacturing.doctype.manufacturing_settings.manufacturing_settings import get_mins_between_operations class OverlapError(frappe.ValidationError): pass class OverProductionLoggedError(frappe.ValidationError): pass @@ -182,9 +183,14 @@ class TimeLog(Document): def move_to_next_non_overlapping_slot(self): """If in overlap, set start as the end point of the overlapping time log""" - overlapping = self.get_overlap_for("workstation") - if overlapping: - self.from_time = get_datetime(overlapping.to_time) + relativedelta(minutes=10) + overlapping = self.get_overlap_for("workstation") \ + or self.get_overlap_for("employee") \ + or self.get_overlap_for("user") + + if not overlapping: + frappe.throw("Logical error: Must find overlapping") + + self.from_time = get_datetime(overlapping.to_time) + get_mins_between_operations() def get_time_log_summary(self): """Returns 'Actual Operating Time'. """