[fix] capacity planning error
diff --git a/erpnext/accounts/doctype/journal_entry/test_journal_entry.py b/erpnext/accounts/doctype/journal_entry/test_journal_entry.py
index c70f10d..8995e34 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 @@
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 5f3d4c8..d12b2d7 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 @@
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 @@
]
})
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 @@
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 @@
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 ab6bbab..3fabae0 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 023c43e..b6befe0 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.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 @@
original_start_time = time_log.from_time
while True:
_from_time = time_log.from_time
+
try:
time_log.save()
break
@@ -248,6 +250,7 @@
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 @@
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 0f50e9c..6e937c0 100644
--- a/erpnext/projects/doctype/time_log/time_log.py
+++ b/erpnext/projects/doctype/time_log/time_log.py
@@ -6,6 +6,7 @@
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 @@
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'. """