feat: add consecutive calendar week (WW) for naming series

The calendar week is based on ISO 8601 but behaves slightly different
for the first and last days of a year to ensure consecutiveness:

* If the first days of a year would be in week 53 then 00 is used
  instead.
* if the last days of a year would be in week 01 then 53 is used
  instead.

Closes #14413
This commit is contained in:
Daniel Gerhardt 2021-10-18 14:04:53 +02:00
parent a59c37465f
commit 16dca0b1c1
2 changed files with 73 additions and 0 deletions

View file

@ -175,6 +175,8 @@ def parse_naming_series(parts, doctype='', doc=''):
part = today.strftime("%d")
elif e == 'YYYY':
part = today.strftime('%Y')
elif e == 'WW':
part = determine_consecutive_week_number(today)
elif e == 'timestamp':
part = str(today)
elif e == 'FY':
@ -193,6 +195,19 @@ def parse_naming_series(parts, doctype='', doc=''):
return n
def determine_consecutive_week_number(datetime):
"""Determines the consecutive calendar week"""
m = datetime.month
# ISO 8601 calandar week
w = datetime.strftime('%V')
# Ensure consecutiveness for the first and last days of a year
if m == 1 and int(w) >= 52:
w = '00'
elif m == 12 and int(w) <= 1:
w = '53'
return w
def getseries(key, digits):
# series created ?
# Using frappe.qb as frappe.get_values does not allow order_by=None

View file

@ -7,6 +7,7 @@ from frappe.utils import now_datetime
from frappe.model.naming import getseries
from frappe.model.naming import append_number_if_name_exists, revert_series_if_last
from frappe.model.naming import determine_consecutive_week_number, parse_naming_series
class TestNaming(unittest.TestCase):
def tearDown(self):
@ -60,6 +61,34 @@ class TestNaming(unittest.TestCase):
self.assertEqual(todo.name, 'TODO-{month}-{status}-{series}'.format(
month=now_datetime().strftime('%m'), status=todo.status, series=series))
def test_format_autoname_for_consecutive_week_number(self):
'''
Test if braced params are replaced for consecutive week number in format autoname
'''
doctype = 'ToDo'
todo_doctype = frappe.get_doc('DocType', doctype)
todo_doctype.autoname = 'format:TODO-{WW}-{##}'
todo_doctype.save()
description = 'Format'
todo = frappe.new_doc(doctype)
todo.description = description
todo.insert()
series = getseries('', 2)
series = str(int(series)-1)
if len(series) < 2:
series = '0' + series
week = determine_consecutive_week_number(now_datetime())
self.assertEqual(todo.name, 'TODO-{week}-{series}'.format(
week=week, series=series))
def test_revert_series(self):
from datetime import datetime
year = datetime.now().year
@ -150,3 +179,32 @@ class TestNaming(unittest.TestCase):
self.assertEqual(amended_doc.name, "{}-CANC-1".format(original_name))
submittable_doctype.delete()
def test_parse_naming_series_for_consecutive_week_number(self):
week = determine_consecutive_week_number(now_datetime())
name = parse_naming_series('PREFIX-.WW.-SUFFIX')
expected_name = 'PREFIX-{}-SUFFIX'.format(week)
self.assertEqual(name, expected_name)
def test_determine_consecutive_week_number(self):
from datetime import datetime
dt = datetime.fromisoformat("2019-12-31")
w = determine_consecutive_week_number(dt)
self.assertEqual(w, "53")
dt = datetime.fromisoformat("2020-01-01")
w = determine_consecutive_week_number(dt)
self.assertEqual(w, "01")
dt = datetime.fromisoformat("2020-01-15")
w = determine_consecutive_week_number(dt)
self.assertEqual(w, "03")
dt = datetime.fromisoformat("2021-01-01")
w = determine_consecutive_week_number(dt)
self.assertEqual(w, "00")
dt = datetime.fromisoformat("2021-12-31")
w = determine_consecutive_week_number(dt)
self.assertEqual(w, "52")