From 8153e1f713db60f3543c5e1cbd4339e31f82829a Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Fri, 1 Oct 2021 12:05:12 +0530 Subject: [PATCH] fix: option to limit reposting in certain timeslot --- .../repost_item_valuation.py | 28 +++++++- .../test_repost_item_valuation.py | 71 ++++++++++++++++-- .../stock_reposting_settings/__init__.py | 0 .../stock_reposting_settings.js | 8 +++ .../stock_reposting_settings.json | 72 +++++++++++++++++++ .../stock_reposting_settings.py | 28 ++++++++ .../test_stock_reposting_settings.py | 9 +++ 7 files changed, 210 insertions(+), 6 deletions(-) create mode 100644 erpnext/stock/doctype/stock_reposting_settings/__init__.py create mode 100644 erpnext/stock/doctype/stock_reposting_settings/stock_reposting_settings.js create mode 100644 erpnext/stock/doctype/stock_reposting_settings/stock_reposting_settings.json create mode 100644 erpnext/stock/doctype/stock_reposting_settings/stock_reposting_settings.py create mode 100644 erpnext/stock/doctype/stock_reposting_settings/test_stock_reposting_settings.py diff --git a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py index 62b3a6adf7f5..d86e52fa641d 100644 --- a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py +++ b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py @@ -7,7 +7,7 @@ import frappe from frappe import _ from frappe.model.document import Document -from frappe.utils import cint, get_link_to_form, now, today +from frappe.utils import cint, get_link_to_form, get_weekday, now, nowtime, today from frappe.utils.user import get_users_with_role from rq.timeouts import JobTimeoutException @@ -126,6 +126,9 @@ def notify_error_to_stock_managers(doc, traceback): frappe.sendmail(recipients=recipients, subject=subject, message=message) def repost_entries(): + if not in_configured_timeslot(): + return + riv_entries = get_repost_item_valuation_entries() for row in riv_entries: @@ -144,3 +147,26 @@ def get_repost_item_valuation_entries(): WHERE status in ('Queued', 'In Progress') and creation <= %s and docstatus = 1 ORDER BY timestamp(posting_date, posting_time) asc, creation asc """, now(), as_dict=1) + + +def in_configured_timeslot(repost_settings=None, current_time=None): + """Check if current time is in configured timeslot for reposting.""" + + if repost_settings is None: + repost_settings = frappe.get_cached_doc("Stock Reposting Settings") + + if not repost_settings.limit_reposting_timeslot: + return True + + if get_weekday() == repost_settings.limits_dont_apply_on: + return True + + start_time = repost_settings.start_time + end_time = repost_settings.end_time + + now_time = current_time or nowtime() + + if start_time < end_time: + return end_time >= now_time >= start_time + else: + return now_time >= start_time or now_time <= end_time diff --git a/erpnext/stock/doctype/repost_item_valuation/test_repost_item_valuation.py b/erpnext/stock/doctype/repost_item_valuation/test_repost_item_valuation.py index c70a9ec7a8ba..c086f938b5d4 100644 --- a/erpnext/stock/doctype/repost_item_valuation/test_repost_item_valuation.py +++ b/erpnext/stock/doctype/repost_item_valuation/test_repost_item_valuation.py @@ -1,11 +1,72 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors +# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -from __future__ import unicode_literals -# import frappe import unittest +import frappe + +from erpnext.stock.doctype.repost_item_valuation.repost_item_valuation import ( + in_configured_timeslot, +) + class TestRepostItemValuation(unittest.TestCase): - pass + def test_repost_time_slot(self): + repost_settings = frappe.get_doc("Stock Reposting Settings") + + positive_cases = [ + {"limit_reposting_timeslot": 0}, + { + "limit_reposting_timeslot": 1, + "start_time": "18:00:00", + "end_time": "09:00:00", + "current_time": "20:00:00", + }, + { + "limit_reposting_timeslot": 1, + "start_time": "09:00:00", + "end_time": "18:00:00", + "current_time": "12:00:00", + }, + { + "limit_reposting_timeslot": 1, + "start_time": "23:00:00", + "end_time": "09:00:00", + "current_time": "2:00:00", + }, + ] + + for case in positive_cases: + repost_settings.update(case) + self.assertTrue( + in_configured_timeslot(repost_settings, case.get("current_time")), + msg=f"Exepcted true from : {case}", + ) + + negative_cases = [ + { + "limit_reposting_timeslot": 1, + "start_time": "18:00:00", + "end_time": "09:00:00", + "current_time": "09:01:00", + }, + { + "limit_reposting_timeslot": 1, + "start_time": "09:00:00", + "end_time": "18:00:00", + "current_time": "19:00:00", + }, + { + "limit_reposting_timeslot": 1, + "start_time": "23:00:00", + "end_time": "09:00:00", + "current_time": "22:00:00", + }, + ] + + for case in negative_cases: + repost_settings.update(case) + self.assertFalse( + in_configured_timeslot(repost_settings, case.get("current_time")), + msg=f"Exepcted false from : {case}", + ) diff --git a/erpnext/stock/doctype/stock_reposting_settings/__init__.py b/erpnext/stock/doctype/stock_reposting_settings/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/erpnext/stock/doctype/stock_reposting_settings/stock_reposting_settings.js b/erpnext/stock/doctype/stock_reposting_settings/stock_reposting_settings.js new file mode 100644 index 000000000000..42d0723d4276 --- /dev/null +++ b/erpnext/stock/doctype/stock_reposting_settings/stock_reposting_settings.js @@ -0,0 +1,8 @@ +// Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Stock Reposting Settings', { + // refresh: function(frm) { + + // } +}); diff --git a/erpnext/stock/doctype/stock_reposting_settings/stock_reposting_settings.json b/erpnext/stock/doctype/stock_reposting_settings/stock_reposting_settings.json new file mode 100644 index 000000000000..24740590037a --- /dev/null +++ b/erpnext/stock/doctype/stock_reposting_settings/stock_reposting_settings.json @@ -0,0 +1,72 @@ +{ + "actions": [], + "allow_rename": 1, + "creation": "2021-10-01 10:56:30.814787", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "scheduling_section", + "limit_reposting_timeslot", + "start_time", + "end_time", + "limits_dont_apply_on" + ], + "fields": [ + { + "fieldname": "scheduling_section", + "fieldtype": "Section Break", + "label": "Scheduling" + }, + { + "depends_on": "limit_reposting_timeslot", + "fieldname": "start_time", + "fieldtype": "Time", + "label": "Start Time", + "mandatory_depends_on": "limit_reposting_timeslot" + }, + { + "depends_on": "limit_reposting_timeslot", + "fieldname": "end_time", + "fieldtype": "Time", + "label": "End Time", + "mandatory_depends_on": "limit_reposting_timeslot" + }, + { + "depends_on": "limit_reposting_timeslot", + "fieldname": "limits_dont_apply_on", + "fieldtype": "Select", + "label": "Limits don't apply on", + "options": "\nMonday\nTuesday\nWednesday\nThursday\nFriday\nSaturday\nSunday" + }, + { + "default": "0", + "fieldname": "limit_reposting_timeslot", + "fieldtype": "Check", + "label": "Limit timeslot for Stock Reposting" + } + ], + "index_web_pages_for_search": 1, + "issingle": 1, + "links": [], + "modified": "2021-10-01 11:27:28.981594", + "modified_by": "Administrator", + "module": "Stock", + "name": "Stock Reposting Settings", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "print": 1, + "read": 1, + "role": "System Manager", + "share": 1, + "write": 1 + } + ], + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 +} \ No newline at end of file diff --git a/erpnext/stock/doctype/stock_reposting_settings/stock_reposting_settings.py b/erpnext/stock/doctype/stock_reposting_settings/stock_reposting_settings.py new file mode 100644 index 000000000000..bab521d69fc1 --- /dev/null +++ b/erpnext/stock/doctype/stock_reposting_settings/stock_reposting_settings.py @@ -0,0 +1,28 @@ +# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from frappe.model.document import Document +from frappe.utils import add_to_date, get_datetime, get_time_str, time_diff_in_hours + + +class StockRepostingSettings(Document): + + + def validate(self): + self.set_minimum_reposting_time_slot() + + def set_minimum_reposting_time_slot(self): + """Ensure that timeslot for reposting is at least 12 hours.""" + if not self.limit_reposting_timeslot: + return + + start_time = get_datetime(self.start_time) + end_time = get_datetime(self.end_time) + + if start_time > end_time: + end_time = add_to_date(end_time, days=1, as_datetime=True) + + diff = time_diff_in_hours(end_time, start_time) + + if diff < 10: + self.end_time = get_time_str(add_to_date(self.start_time, hours=10, as_datetime=True)) diff --git a/erpnext/stock/doctype/stock_reposting_settings/test_stock_reposting_settings.py b/erpnext/stock/doctype/stock_reposting_settings/test_stock_reposting_settings.py new file mode 100644 index 000000000000..fad74d355cfd --- /dev/null +++ b/erpnext/stock/doctype/stock_reposting_settings/test_stock_reposting_settings.py @@ -0,0 +1,9 @@ +# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt + +# import frappe +import unittest + + +class TestStockRepostingSettings(unittest.TestCase): + pass