Merge branch 'develop' into stock-analytics
This commit is contained in:
commit
42899d69ea
@ -58,8 +58,8 @@ class GLEntry(Document):
|
|||||||
if not self.get(k):
|
if not self.get(k):
|
||||||
frappe.throw(_("{0} is required").format(_(self.meta.get_label(k))))
|
frappe.throw(_("{0} is required").format(_(self.meta.get_label(k))))
|
||||||
|
|
||||||
account_type = frappe.get_cached_value("Account", self.account, "account_type")
|
|
||||||
if not (self.party_type and self.party):
|
if not (self.party_type and self.party):
|
||||||
|
account_type = frappe.get_cached_value("Account", self.account, "account_type")
|
||||||
if account_type == "Receivable":
|
if account_type == "Receivable":
|
||||||
frappe.throw(_("{0} {1}: Customer is required against Receivable account {2}")
|
frappe.throw(_("{0} {1}: Customer is required against Receivable account {2}")
|
||||||
.format(self.voucher_type, self.voucher_no, self.account))
|
.format(self.voucher_type, self.voucher_no, self.account))
|
||||||
@ -73,15 +73,19 @@ class GLEntry(Document):
|
|||||||
.format(self.voucher_type, self.voucher_no, self.account))
|
.format(self.voucher_type, self.voucher_no, self.account))
|
||||||
|
|
||||||
def pl_must_have_cost_center(self):
|
def pl_must_have_cost_center(self):
|
||||||
if frappe.get_cached_value("Account", self.account, "report_type") == "Profit and Loss":
|
"""Validate that profit and loss type account GL entries have a cost center."""
|
||||||
if not self.cost_center and self.voucher_type != 'Period Closing Voucher':
|
|
||||||
msg = _("{0} {1}: Cost Center is required for 'Profit and Loss' account {2}.").format(
|
|
||||||
self.voucher_type, self.voucher_no, self.account)
|
|
||||||
msg += " "
|
|
||||||
msg += _("Please set the cost center field in {0} or setup a default Cost Center for the Company.").format(
|
|
||||||
self.voucher_type)
|
|
||||||
|
|
||||||
frappe.throw(msg, title=_("Missing Cost Center"))
|
if self.cost_center or self.voucher_type == 'Period Closing Voucher':
|
||||||
|
return
|
||||||
|
|
||||||
|
if frappe.get_cached_value("Account", self.account, "report_type") == "Profit and Loss":
|
||||||
|
msg = _("{0} {1}: Cost Center is required for 'Profit and Loss' account {2}.").format(
|
||||||
|
self.voucher_type, self.voucher_no, self.account)
|
||||||
|
msg += " "
|
||||||
|
msg += _("Please set the cost center field in {0} or setup a default Cost Center for the Company.").format(
|
||||||
|
self.voucher_type)
|
||||||
|
|
||||||
|
frappe.throw(msg, title=_("Missing Cost Center"))
|
||||||
|
|
||||||
def validate_dimensions_for_pl_and_bs(self):
|
def validate_dimensions_for_pl_and_bs(self):
|
||||||
account_type = frappe.db.get_value("Account", self.account, "report_type")
|
account_type = frappe.db.get_value("Account", self.account, "report_type")
|
||||||
|
@ -100,8 +100,8 @@ def merge_similar_entries(gl_map, precision=None):
|
|||||||
return merged_gl_map
|
return merged_gl_map
|
||||||
|
|
||||||
def check_if_in_list(gle, gl_map, dimensions=None):
|
def check_if_in_list(gle, gl_map, dimensions=None):
|
||||||
account_head_fieldnames = ['party_type', 'party', 'against_voucher', 'against_voucher_type',
|
account_head_fieldnames = ['voucher_detail_no', 'party', 'against_voucher',
|
||||||
'cost_center', 'project', 'voucher_detail_no']
|
'cost_center', 'against_voucher_type', 'party_type', 'project']
|
||||||
|
|
||||||
if dimensions:
|
if dimensions:
|
||||||
account_head_fieldnames = account_head_fieldnames + dimensions
|
account_head_fieldnames = account_head_fieldnames + dimensions
|
||||||
@ -110,10 +110,12 @@ def check_if_in_list(gle, gl_map, dimensions=None):
|
|||||||
same_head = True
|
same_head = True
|
||||||
if e.account != gle.account:
|
if e.account != gle.account:
|
||||||
same_head = False
|
same_head = False
|
||||||
|
continue
|
||||||
|
|
||||||
for fieldname in account_head_fieldnames:
|
for fieldname in account_head_fieldnames:
|
||||||
if cstr(e.get(fieldname)) != cstr(gle.get(fieldname)):
|
if cstr(e.get(fieldname)) != cstr(gle.get(fieldname)):
|
||||||
same_head = False
|
same_head = False
|
||||||
|
break
|
||||||
|
|
||||||
if same_head:
|
if same_head:
|
||||||
return e
|
return e
|
||||||
@ -143,16 +145,19 @@ def make_entry(args, adv_adj, update_outstanding, from_repost=False):
|
|||||||
validate_expense_against_budget(args)
|
validate_expense_against_budget(args)
|
||||||
|
|
||||||
def validate_cwip_accounts(gl_map):
|
def validate_cwip_accounts(gl_map):
|
||||||
cwip_enabled = any(cint(ac.enable_cwip_accounting) for ac in frappe.db.get_all("Asset Category","enable_cwip_accounting"))
|
"""Validate that CWIP account are not used in Journal Entry"""
|
||||||
|
if gl_map and gl_map[0].voucher_type != "Journal Entry":
|
||||||
|
return
|
||||||
|
|
||||||
if cwip_enabled and gl_map[0].voucher_type == "Journal Entry":
|
cwip_enabled = any(cint(ac.enable_cwip_accounting) for ac in frappe.db.get_all("Asset Category", "enable_cwip_accounting"))
|
||||||
cwip_accounts = [d[0] for d in frappe.db.sql("""select name from tabAccount
|
if cwip_enabled:
|
||||||
where account_type = 'Capital Work in Progress' and is_group=0""")]
|
cwip_accounts = [d[0] for d in frappe.db.sql("""select name from tabAccount
|
||||||
|
where account_type = 'Capital Work in Progress' and is_group=0""")]
|
||||||
|
|
||||||
for entry in gl_map:
|
for entry in gl_map:
|
||||||
if entry.account in cwip_accounts:
|
if entry.account in cwip_accounts:
|
||||||
frappe.throw(
|
frappe.throw(
|
||||||
_("Account: <b>{0}</b> is capital Work in progress and can not be updated by Journal Entry").format(entry.account))
|
_("Account: <b>{0}</b> is capital Work in progress and can not be updated by Journal Entry").format(entry.account))
|
||||||
|
|
||||||
def round_off_debit_credit(gl_map):
|
def round_off_debit_credit(gl_map):
|
||||||
precision = get_field_precision(frappe.get_meta("GL Entry").get_field("debit"),
|
precision = get_field_precision(frappe.get_meta("GL Entry").get_field("debit"),
|
||||||
|
@ -920,7 +920,6 @@ def repost_gle_for_stock_vouchers(stock_vouchers, posting_date, company=None, wa
|
|||||||
_delete_gl_entries(voucher_type, voucher_no)
|
_delete_gl_entries(voucher_type, voucher_no)
|
||||||
|
|
||||||
def get_future_stock_vouchers(posting_date, posting_time, for_warehouses=None, for_items=None, company=None):
|
def get_future_stock_vouchers(posting_date, posting_time, for_warehouses=None, for_items=None, company=None):
|
||||||
future_stock_vouchers = []
|
|
||||||
|
|
||||||
values = []
|
values = []
|
||||||
condition = ""
|
condition = ""
|
||||||
@ -936,30 +935,46 @@ def get_future_stock_vouchers(posting_date, posting_time, for_warehouses=None, f
|
|||||||
condition += " and company = %s"
|
condition += " and company = %s"
|
||||||
values.append(company)
|
values.append(company)
|
||||||
|
|
||||||
for d in frappe.db.sql("""select distinct sle.voucher_type, sle.voucher_no
|
future_stock_vouchers = frappe.db.sql("""select distinct sle.voucher_type, sle.voucher_no
|
||||||
from `tabStock Ledger Entry` sle
|
from `tabStock Ledger Entry` sle
|
||||||
where
|
where
|
||||||
timestamp(sle.posting_date, sle.posting_time) >= timestamp(%s, %s)
|
timestamp(sle.posting_date, sle.posting_time) >= timestamp(%s, %s)
|
||||||
and is_cancelled = 0
|
and is_cancelled = 0
|
||||||
{condition}
|
{condition}
|
||||||
order by timestamp(sle.posting_date, sle.posting_time) asc, creation asc for update""".format(condition=condition),
|
order by timestamp(sle.posting_date, sle.posting_time) asc, creation asc for update""".format(condition=condition),
|
||||||
tuple([posting_date, posting_time] + values), as_dict=True):
|
tuple([posting_date, posting_time] + values), as_dict=True)
|
||||||
future_stock_vouchers.append([d.voucher_type, d.voucher_no])
|
|
||||||
|
|
||||||
return future_stock_vouchers
|
return [(d.voucher_type, d.voucher_no) for d in future_stock_vouchers]
|
||||||
|
|
||||||
def get_voucherwise_gl_entries(future_stock_vouchers, posting_date):
|
def get_voucherwise_gl_entries(future_stock_vouchers, posting_date):
|
||||||
|
""" Get voucherwise list of GL entries.
|
||||||
|
|
||||||
|
Only fetches GLE fields required for comparing with new GLE.
|
||||||
|
Check compare_existing_and_expected_gle function below.
|
||||||
|
"""
|
||||||
gl_entries = {}
|
gl_entries = {}
|
||||||
if future_stock_vouchers:
|
if not future_stock_vouchers:
|
||||||
for d in frappe.db.sql("""select * from `tabGL Entry`
|
return gl_entries
|
||||||
where posting_date >= %s and voucher_no in (%s)""" %
|
|
||||||
('%s', ', '.join(['%s']*len(future_stock_vouchers))),
|
voucher_nos = [d[1] for d in future_stock_vouchers]
|
||||||
tuple([posting_date] + [d[1] for d in future_stock_vouchers]), as_dict=1):
|
|
||||||
gl_entries.setdefault((d.voucher_type, d.voucher_no), []).append(d)
|
gles = frappe.db.sql("""
|
||||||
|
select name, account, credit, debit, cost_center, project
|
||||||
|
from `tabGL Entry`
|
||||||
|
where
|
||||||
|
posting_date >= %s and voucher_no in (%s)""" %
|
||||||
|
('%s', ', '.join(['%s'] * len(voucher_nos))),
|
||||||
|
tuple([posting_date] + voucher_nos), as_dict=1)
|
||||||
|
|
||||||
|
for d in gles:
|
||||||
|
gl_entries.setdefault((d.voucher_type, d.voucher_no), []).append(d)
|
||||||
|
|
||||||
return gl_entries
|
return gl_entries
|
||||||
|
|
||||||
def compare_existing_and_expected_gle(existing_gle, expected_gle, precision):
|
def compare_existing_and_expected_gle(existing_gle, expected_gle, precision):
|
||||||
|
if len(existing_gle) != len(expected_gle):
|
||||||
|
return False
|
||||||
|
|
||||||
matched = True
|
matched = True
|
||||||
for entry in expected_gle:
|
for entry in expected_gle:
|
||||||
account_existed = False
|
account_existed = False
|
||||||
|
@ -15,6 +15,7 @@ from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_pu
|
|||||||
|
|
||||||
class TestAssetMovement(unittest.TestCase):
|
class TestAssetMovement(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
frappe.db.set_value("Company", "_Test Company", "capital_work_in_progress_account", "CWIP Account - _TC")
|
||||||
create_asset_data()
|
create_asset_data()
|
||||||
make_location()
|
make_location()
|
||||||
|
|
||||||
@ -45,12 +46,12 @@ class TestAssetMovement(unittest.TestCase):
|
|||||||
'location_name': 'Test Location 2'
|
'location_name': 'Test Location 2'
|
||||||
}).insert()
|
}).insert()
|
||||||
|
|
||||||
movement1 = create_asset_movement(purpose = 'Transfer', company = asset.company,
|
movement1 = create_asset_movement(purpose = 'Transfer', company = asset.company,
|
||||||
assets = [{ 'asset': asset.name , 'source_location': 'Test Location', 'target_location': 'Test Location 2'}],
|
assets = [{ 'asset': asset.name , 'source_location': 'Test Location', 'target_location': 'Test Location 2'}],
|
||||||
reference_doctype = 'Purchase Receipt', reference_name = pr.name)
|
reference_doctype = 'Purchase Receipt', reference_name = pr.name)
|
||||||
self.assertEqual(frappe.db.get_value("Asset", asset.name, "location"), "Test Location 2")
|
self.assertEqual(frappe.db.get_value("Asset", asset.name, "location"), "Test Location 2")
|
||||||
|
|
||||||
movement2 = create_asset_movement(purpose = 'Transfer', company = asset.company,
|
create_asset_movement(purpose = 'Transfer', company = asset.company,
|
||||||
assets = [{ 'asset': asset.name , 'source_location': 'Test Location 2', 'target_location': 'Test Location'}],
|
assets = [{ 'asset': asset.name , 'source_location': 'Test Location 2', 'target_location': 'Test Location'}],
|
||||||
reference_doctype = 'Purchase Receipt', reference_name = pr.name)
|
reference_doctype = 'Purchase Receipt', reference_name = pr.name)
|
||||||
self.assertEqual(frappe.db.get_value("Asset", asset.name, "location"), "Test Location")
|
self.assertEqual(frappe.db.get_value("Asset", asset.name, "location"), "Test Location")
|
||||||
@ -59,18 +60,18 @@ class TestAssetMovement(unittest.TestCase):
|
|||||||
self.assertEqual(frappe.db.get_value("Asset", asset.name, "location"), "Test Location")
|
self.assertEqual(frappe.db.get_value("Asset", asset.name, "location"), "Test Location")
|
||||||
|
|
||||||
employee = make_employee("testassetmovemp@example.com", company="_Test Company")
|
employee = make_employee("testassetmovemp@example.com", company="_Test Company")
|
||||||
movement3 = create_asset_movement(purpose = 'Issue', company = asset.company,
|
create_asset_movement(purpose = 'Issue', company = asset.company,
|
||||||
assets = [{ 'asset': asset.name , 'source_location': 'Test Location', 'to_employee': employee}],
|
assets = [{ 'asset': asset.name , 'source_location': 'Test Location', 'to_employee': employee}],
|
||||||
reference_doctype = 'Purchase Receipt', reference_name = pr.name)
|
reference_doctype = 'Purchase Receipt', reference_name = pr.name)
|
||||||
|
|
||||||
# after issuing asset should belong to an employee not at a location
|
# after issuing asset should belong to an employee not at a location
|
||||||
self.assertEqual(frappe.db.get_value("Asset", asset.name, "location"), None)
|
self.assertEqual(frappe.db.get_value("Asset", asset.name, "location"), None)
|
||||||
self.assertEqual(frappe.db.get_value("Asset", asset.name, "custodian"), employee)
|
self.assertEqual(frappe.db.get_value("Asset", asset.name, "custodian"), employee)
|
||||||
|
|
||||||
def test_last_movement_cancellation(self):
|
def test_last_movement_cancellation(self):
|
||||||
pr = make_purchase_receipt(item_code="Macbook Pro",
|
pr = make_purchase_receipt(item_code="Macbook Pro",
|
||||||
qty=1, rate=100000.0, location="Test Location")
|
qty=1, rate=100000.0, location="Test Location")
|
||||||
|
|
||||||
asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name')
|
asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name')
|
||||||
asset = frappe.get_doc('Asset', asset_name)
|
asset = frappe.get_doc('Asset', asset_name)
|
||||||
asset.calculate_depreciation = 1
|
asset.calculate_depreciation = 1
|
||||||
@ -85,17 +86,17 @@ class TestAssetMovement(unittest.TestCase):
|
|||||||
})
|
})
|
||||||
if asset.docstatus == 0:
|
if asset.docstatus == 0:
|
||||||
asset.submit()
|
asset.submit()
|
||||||
|
|
||||||
if not frappe.db.exists("Location", "Test Location 2"):
|
if not frappe.db.exists("Location", "Test Location 2"):
|
||||||
frappe.get_doc({
|
frappe.get_doc({
|
||||||
'doctype': 'Location',
|
'doctype': 'Location',
|
||||||
'location_name': 'Test Location 2'
|
'location_name': 'Test Location 2'
|
||||||
}).insert()
|
}).insert()
|
||||||
|
|
||||||
movement = frappe.get_doc({'doctype': 'Asset Movement', 'reference_name': pr.name })
|
movement = frappe.get_doc({'doctype': 'Asset Movement', 'reference_name': pr.name })
|
||||||
self.assertRaises(frappe.ValidationError, movement.cancel)
|
self.assertRaises(frappe.ValidationError, movement.cancel)
|
||||||
|
|
||||||
movement1 = create_asset_movement(purpose = 'Transfer', company = asset.company,
|
movement1 = create_asset_movement(purpose = 'Transfer', company = asset.company,
|
||||||
assets = [{ 'asset': asset.name , 'source_location': 'Test Location', 'target_location': 'Test Location 2'}],
|
assets = [{ 'asset': asset.name , 'source_location': 'Test Location', 'target_location': 'Test Location 2'}],
|
||||||
reference_doctype = 'Purchase Receipt', reference_name = pr.name)
|
reference_doctype = 'Purchase Receipt', reference_name = pr.name)
|
||||||
self.assertEqual(frappe.db.get_value("Asset", asset.name, "location"), "Test Location 2")
|
self.assertEqual(frappe.db.get_value("Asset", asset.name, "location"), "Test Location 2")
|
||||||
|
@ -15,7 +15,11 @@ class TestAttendanceRequest(unittest.TestCase):
|
|||||||
for doctype in ["Attendance Request", "Attendance"]:
|
for doctype in ["Attendance Request", "Attendance"]:
|
||||||
frappe.db.sql("delete from `tab{doctype}`".format(doctype=doctype))
|
frappe.db.sql("delete from `tab{doctype}`".format(doctype=doctype))
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
frappe.db.rollback()
|
||||||
|
|
||||||
def test_on_duty_attendance_request(self):
|
def test_on_duty_attendance_request(self):
|
||||||
|
"Test creation/updation of Attendace from Attendance Request, on duty."
|
||||||
today = nowdate()
|
today = nowdate()
|
||||||
employee = get_employee()
|
employee = get_employee()
|
||||||
attendance_request = frappe.new_doc("Attendance Request")
|
attendance_request = frappe.new_doc("Attendance Request")
|
||||||
@ -26,17 +30,36 @@ class TestAttendanceRequest(unittest.TestCase):
|
|||||||
attendance_request.company = "_Test Company"
|
attendance_request.company = "_Test Company"
|
||||||
attendance_request.insert()
|
attendance_request.insert()
|
||||||
attendance_request.submit()
|
attendance_request.submit()
|
||||||
attendance = frappe.get_doc('Attendance', {
|
|
||||||
'employee': employee.name,
|
attendance = frappe.db.get_value(
|
||||||
'attendance_date': date(date.today().year, 1, 1),
|
"Attendance",
|
||||||
'docstatus': 1
|
filters={
|
||||||
})
|
"attendance_request": attendance_request.name,
|
||||||
self.assertEqual(attendance.status, 'Present')
|
"attendance_date": date(date.today().year, 1, 1)
|
||||||
|
},
|
||||||
|
fieldname=["status", "docstatus"],
|
||||||
|
as_dict=True
|
||||||
|
)
|
||||||
|
self.assertEqual(attendance.status, "Present")
|
||||||
|
self.assertEqual(attendance.docstatus, 1)
|
||||||
|
|
||||||
|
# cancelling attendance request cancels linked attendances
|
||||||
attendance_request.cancel()
|
attendance_request.cancel()
|
||||||
attendance.reload()
|
|
||||||
self.assertEqual(attendance.docstatus, 2)
|
# cancellation alters docname
|
||||||
|
# fetch attendance value again to avoid stale docname
|
||||||
|
attendance_docstatus = frappe.db.get_value(
|
||||||
|
"Attendance",
|
||||||
|
filters={
|
||||||
|
"attendance_request": attendance_request.name,
|
||||||
|
"attendance_date": date(date.today().year, 1, 1)
|
||||||
|
},
|
||||||
|
fieldname="docstatus"
|
||||||
|
)
|
||||||
|
self.assertEqual(attendance_docstatus, 2)
|
||||||
|
|
||||||
def test_work_from_home_attendance_request(self):
|
def test_work_from_home_attendance_request(self):
|
||||||
|
"Test creation/updation of Attendace from Attendance Request, work from home."
|
||||||
today = nowdate()
|
today = nowdate()
|
||||||
employee = get_employee()
|
employee = get_employee()
|
||||||
attendance_request = frappe.new_doc("Attendance Request")
|
attendance_request = frappe.new_doc("Attendance Request")
|
||||||
@ -47,15 +70,30 @@ class TestAttendanceRequest(unittest.TestCase):
|
|||||||
attendance_request.company = "_Test Company"
|
attendance_request.company = "_Test Company"
|
||||||
attendance_request.insert()
|
attendance_request.insert()
|
||||||
attendance_request.submit()
|
attendance_request.submit()
|
||||||
attendance = frappe.get_doc('Attendance', {
|
|
||||||
'employee': employee.name,
|
attendance_status = frappe.db.get_value(
|
||||||
'attendance_date': date(date.today().year, 1, 1),
|
"Attendance",
|
||||||
'docstatus': 1
|
filters={
|
||||||
})
|
"attendance_request": attendance_request.name,
|
||||||
self.assertEqual(attendance.status, 'Work From Home')
|
"attendance_date": date(date.today().year, 1, 1)
|
||||||
|
},
|
||||||
|
fieldname="status"
|
||||||
|
)
|
||||||
|
self.assertEqual(attendance_status, 'Work From Home')
|
||||||
|
|
||||||
attendance_request.cancel()
|
attendance_request.cancel()
|
||||||
attendance.reload()
|
|
||||||
self.assertEqual(attendance.docstatus, 2)
|
# cancellation alters docname
|
||||||
|
# fetch attendance value again to avoid stale docname
|
||||||
|
attendance_docstatus = frappe.db.get_value(
|
||||||
|
"Attendance",
|
||||||
|
filters={
|
||||||
|
"attendance_request": attendance_request.name,
|
||||||
|
"attendance_date": date(date.today().year, 1, 1)
|
||||||
|
},
|
||||||
|
fieldname="docstatus"
|
||||||
|
)
|
||||||
|
self.assertEqual(attendance_docstatus, 2)
|
||||||
|
|
||||||
def get_employee():
|
def get_employee():
|
||||||
return frappe.get_doc("Employee", "_T-Employee-00001")
|
return frappe.get_doc("Employee", "_T-Employee-00001")
|
||||||
|
@ -15,24 +15,35 @@ class TestShiftRequest(unittest.TestCase):
|
|||||||
for doctype in ["Shift Request", "Shift Assignment"]:
|
for doctype in ["Shift Request", "Shift Assignment"]:
|
||||||
frappe.db.sql("delete from `tab{doctype}`".format(doctype=doctype))
|
frappe.db.sql("delete from `tab{doctype}`".format(doctype=doctype))
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
frappe.db.rollback()
|
||||||
|
|
||||||
def test_make_shift_request(self):
|
def test_make_shift_request(self):
|
||||||
|
"Test creation/updation of Shift Assignment from Shift Request."
|
||||||
department = frappe.get_value("Employee", "_T-Employee-00001", 'department')
|
department = frappe.get_value("Employee", "_T-Employee-00001", 'department')
|
||||||
set_shift_approver(department)
|
set_shift_approver(department)
|
||||||
approver = frappe.db.sql("""select approver from `tabDepartment Approver` where parent= %s and parentfield = 'shift_request_approver'""", (department))[0][0]
|
approver = frappe.db.sql("""select approver from `tabDepartment Approver` where parent= %s and parentfield = 'shift_request_approver'""", (department))[0][0]
|
||||||
|
|
||||||
shift_request = make_shift_request(approver)
|
shift_request = make_shift_request(approver)
|
||||||
|
|
||||||
shift_assignments = frappe.db.sql('''
|
# Only one shift assignment is created against a shift request
|
||||||
SELECT shift_request, employee
|
shift_assignment = frappe.db.get_value(
|
||||||
FROM `tabShift Assignment`
|
"Shift Assignment",
|
||||||
WHERE shift_request = '{0}'
|
filters={"shift_request": shift_request.name},
|
||||||
'''.format(shift_request.name), as_dict=1)
|
fieldname=["employee", "docstatus"],
|
||||||
for d in shift_assignments:
|
as_dict=True
|
||||||
employee = d.get('employee')
|
)
|
||||||
self.assertEqual(shift_request.employee, employee)
|
self.assertEqual(shift_request.employee, shift_assignment.employee)
|
||||||
shift_request.cancel()
|
self.assertEqual(shift_assignment.docstatus, 1)
|
||||||
shift_assignment_doc = frappe.get_doc("Shift Assignment", {"shift_request": d.get('shift_request')})
|
|
||||||
self.assertEqual(shift_assignment_doc.docstatus, 2)
|
shift_request.cancel()
|
||||||
|
|
||||||
|
shift_assignment_docstatus = frappe.db.get_value(
|
||||||
|
"Shift Assignment",
|
||||||
|
filters={"shift_request": shift_request.name},
|
||||||
|
fieldname="docstatus"
|
||||||
|
)
|
||||||
|
self.assertEqual(shift_assignment_docstatus, 2)
|
||||||
|
|
||||||
def test_shift_request_approver_perms(self):
|
def test_shift_request_approver_perms(self):
|
||||||
employee = frappe.get_doc("Employee", "_T-Employee-00001")
|
employee = frappe.get_doc("Employee", "_T-Employee-00001")
|
||||||
|
@ -673,6 +673,8 @@ class TestSalesOrder(unittest.TestCase):
|
|||||||
|
|
||||||
so.cancel()
|
so.cancel()
|
||||||
|
|
||||||
|
dn.load_from_db()
|
||||||
|
|
||||||
self.assertRaises(frappe.CancelledLinkError, dn.submit)
|
self.assertRaises(frappe.CancelledLinkError, dn.submit)
|
||||||
|
|
||||||
def test_service_type_product_bundle(self):
|
def test_service_type_product_bundle(self):
|
||||||
|
@ -55,8 +55,8 @@ class StockLedgerEntry(Document):
|
|||||||
"sum(actual_qty)") or 0
|
"sum(actual_qty)") or 0
|
||||||
frappe.db.set_value("Batch", self.batch_no, "batch_qty", batch_qty)
|
frappe.db.set_value("Batch", self.batch_no, "batch_qty", batch_qty)
|
||||||
|
|
||||||
#check for item quantity available in stock
|
|
||||||
def actual_amt_check(self):
|
def actual_amt_check(self):
|
||||||
|
"""Validate that qty at warehouse for selected batch is >=0"""
|
||||||
if self.batch_no and not self.get("allow_negative_stock"):
|
if self.batch_no and not self.get("allow_negative_stock"):
|
||||||
batch_bal_after_transaction = flt(frappe.db.sql("""select sum(actual_qty)
|
batch_bal_after_transaction = flt(frappe.db.sql("""select sum(actual_qty)
|
||||||
from `tabStock Ledger Entry`
|
from `tabStock Ledger Entry`
|
||||||
@ -107,7 +107,7 @@ class StockLedgerEntry(Document):
|
|||||||
self.stock_uom = item_det.stock_uom
|
self.stock_uom = item_det.stock_uom
|
||||||
|
|
||||||
def check_stock_frozen_date(self):
|
def check_stock_frozen_date(self):
|
||||||
stock_settings = frappe.get_doc('Stock Settings', 'Stock Settings')
|
stock_settings = frappe.get_cached_doc('Stock Settings')
|
||||||
|
|
||||||
if stock_settings.stock_frozen_upto:
|
if stock_settings.stock_frozen_upto:
|
||||||
if (getdate(self.posting_date) <= getdate(stock_settings.stock_frozen_upto)
|
if (getdate(self.posting_date) <= getdate(stock_settings.stock_frozen_upto)
|
||||||
|
@ -279,15 +279,13 @@ class update_entries_after(object):
|
|||||||
}
|
}
|
||||||
|
|
||||||
"""
|
"""
|
||||||
self.data.setdefault(args.warehouse, frappe._dict())
|
|
||||||
warehouse_dict = self.data[args.warehouse]
|
|
||||||
previous_sle = get_previous_sle_of_current_voucher(args)
|
previous_sle = get_previous_sle_of_current_voucher(args)
|
||||||
warehouse_dict.previous_sle = previous_sle
|
|
||||||
|
|
||||||
for key in ("qty_after_transaction", "valuation_rate", "stock_value"):
|
self.data[args.warehouse] = frappe._dict({
|
||||||
setattr(warehouse_dict, key, flt(previous_sle.get(key)))
|
"previous_sle": previous_sle,
|
||||||
|
"qty_after_transaction": flt(previous_sle.qty_after_transaction),
|
||||||
warehouse_dict.update({
|
"valuation_rate": flt(previous_sle.valuation_rate),
|
||||||
|
"stock_value": flt(previous_sle.stock_value),
|
||||||
"prev_stock_value": previous_sle.stock_value or 0.0,
|
"prev_stock_value": previous_sle.stock_value or 0.0,
|
||||||
"stock_queue": json.loads(previous_sle.stock_queue or "[]"),
|
"stock_queue": json.loads(previous_sle.stock_queue or "[]"),
|
||||||
"stock_value_difference": 0.0
|
"stock_value_difference": 0.0
|
||||||
|
@ -224,7 +224,7 @@ def get_avg_purchase_rate(serial_nos):
|
|||||||
|
|
||||||
def get_valuation_method(item_code):
|
def get_valuation_method(item_code):
|
||||||
"""get valuation method from item or default"""
|
"""get valuation method from item or default"""
|
||||||
val_method = frappe.db.get_value('Item', item_code, 'valuation_method')
|
val_method = frappe.db.get_value('Item', item_code, 'valuation_method', cache=True)
|
||||||
if not val_method:
|
if not val_method:
|
||||||
val_method = frappe.db.get_value("Stock Settings", None, "valuation_method") or "FIFO"
|
val_method = frappe.db.get_value("Stock Settings", None, "valuation_method") or "FIFO"
|
||||||
return val_method
|
return val_method
|
||||||
@ -275,17 +275,17 @@ def get_valid_serial_nos(sr_nos, qty=0, item_code=''):
|
|||||||
return valid_serial_nos
|
return valid_serial_nos
|
||||||
|
|
||||||
def validate_warehouse_company(warehouse, company):
|
def validate_warehouse_company(warehouse, company):
|
||||||
warehouse_company = frappe.db.get_value("Warehouse", warehouse, "company")
|
warehouse_company = frappe.db.get_value("Warehouse", warehouse, "company", cache=True)
|
||||||
if warehouse_company and warehouse_company != company:
|
if warehouse_company and warehouse_company != company:
|
||||||
frappe.throw(_("Warehouse {0} does not belong to company {1}").format(warehouse, company),
|
frappe.throw(_("Warehouse {0} does not belong to company {1}").format(warehouse, company),
|
||||||
InvalidWarehouseCompany)
|
InvalidWarehouseCompany)
|
||||||
|
|
||||||
def is_group_warehouse(warehouse):
|
def is_group_warehouse(warehouse):
|
||||||
if frappe.db.get_value("Warehouse", warehouse, "is_group"):
|
if frappe.db.get_value("Warehouse", warehouse, "is_group", cache=True):
|
||||||
frappe.throw(_("Group node warehouse is not allowed to select for transactions"))
|
frappe.throw(_("Group node warehouse is not allowed to select for transactions"))
|
||||||
|
|
||||||
def validate_disabled_warehouse(warehouse):
|
def validate_disabled_warehouse(warehouse):
|
||||||
if frappe.db.get_value("Warehouse", warehouse, "disabled"):
|
if frappe.db.get_value("Warehouse", warehouse, "disabled", cache=True):
|
||||||
frappe.throw(_("Disabled Warehouse {0} cannot be used for this transaction.").format(get_link_to_form('Warehouse', warehouse)))
|
frappe.throw(_("Disabled Warehouse {0} cannot be used for this transaction.").format(get_link_to_form('Warehouse', warehouse)))
|
||||||
|
|
||||||
def update_included_uom_in_report(columns, result, include_uom, conversion_factors):
|
def update_included_uom_in_report(columns, result, include_uom, conversion_factors):
|
||||||
|
Loading…
Reference in New Issue
Block a user