Skip to content

Commit 517a04e

Browse files
Pawel Zembrzuskipazembrz
authored andcommitted
cnum_provider: fix issues with wrong cnums when holes in cnums sequence
* INSPIR-3236
1 parent ac26f5b commit 517a04e

File tree

2 files changed

+61
-8
lines changed

2 files changed

+61
-8
lines changed

backend/inspirehep/pidstore/providers/cnum.py

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
class InspireCNUMProvider(BaseProvider):
1818
"""CNUM identifier provider."""
19+
1920
pid_type = None
2021
pid_provider = "cnum"
2122
default_status = PIDStatus.RESERVED
@@ -50,15 +51,27 @@ def next(cls, data):
5051
opening_date = data.get("opening_date")
5152
if not opening_date:
5253
return
53-
5454
adjusted_date = datetime.strptime(opening_date, "%Y-%m-%d").strftime("%y-%m-%d")
5555
cnum = f"C{adjusted_date}"
56-
cnums_count = PersistentIdentifier.query\
57-
.filter(PersistentIdentifier.pid_value.like(f"{cnum}%"))\
58-
.filter(PersistentIdentifier.pid_type == "cnum")\
59-
.count()
56+
all_postfixes = []
57+
all_cnums = (
58+
PersistentIdentifier.query.with_for_update()
59+
.filter(PersistentIdentifier.pid_value.like(f"{cnum}%"))
60+
.filter(PersistentIdentifier.pid_type == "cnum")
61+
.all()
62+
)
63+
if not all_cnums:
64+
return cnum
65+
66+
for cnum_entry in all_cnums:
67+
cnum_value = cnum_entry.pid_value.split(".")
68+
if len(cnum_value) > 1:
69+
all_postfixes.append(int(cnum_value[-1]))
70+
if all_postfixes:
71+
postfix = sorted(all_postfixes)[-1] + 1
72+
else:
73+
postfix = 1
6074

61-
if cnums_count > 0:
62-
cnum = f"{cnum}.{cnums_count}"
75+
full_cnum = f"{cnum}.{postfix}"
6376

64-
return cnum
77+
return full_cnum

backend/tests/integration/pidstore/minters/test_minters_cnum.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,3 +189,43 @@ def test_minter_mints_cnum_on_update_when_cnum_is_missing_in_db(
189189
expected_cnum = "C05-01-01"
190190
assert 1 == len(record_cnums)
191191
assert record_cnums[0].pid_value == expected_cnum
192+
193+
194+
def test_generate_cnum_when_holes_in_cnums_sequence(base_app, db, create_record):
195+
data = {"opening_date": "2020-01-01"}
196+
expected_cnum = "C20-01-01.2"
197+
rec1 = create_record("con", data)
198+
rec2 = create_record("con", data)
199+
rec1.hard_delete()
200+
rec3 = create_record("con", data)
201+
assert rec3.get("cnum") == expected_cnum
202+
203+
204+
def test_generate_cnum_when_holes_in_cnums_sequence_and_weird_creation_order(
205+
base_app, db, create_record
206+
):
207+
data = {"opening_date": "2020-01-01", "cnum": "C20-01-01.2"}
208+
rec1 = create_record("con", data)
209+
data["cnum"] = "C20-01-01.1"
210+
rec2 = create_record("con", data)
211+
data["cnum"] = "C20-01-01"
212+
rec3 = create_record("con", data)
213+
del data["cnum"]
214+
rec2.hard_delete()
215+
rec4 = create_record("con", data)
216+
assert rec4["cnum"] == "C20-01-01.3"
217+
218+
219+
def test_generate_cnum_when_holes_in_cnums_sequence_and_big_holes(
220+
base_app, db, create_record
221+
):
222+
data = {"opening_date": "2020-01-01", "cnum": "C20-01-01.20"}
223+
rec1 = create_record("con", data)
224+
data["cnum"] = "C20-01-01.31"
225+
rec2 = create_record("con", data)
226+
data["cnum"] = "C20-01-01.3"
227+
rec3 = create_record("con", data)
228+
del data["cnum"]
229+
rec2.hard_delete()
230+
rec4 = create_record("con", data)
231+
assert rec4["cnum"] == "C20-01-01.21"

0 commit comments

Comments
 (0)