35 lines
1.0 KiB
Python
35 lines
1.0 KiB
Python
"""NCR numbers: the form check and the link to PESCO's NCR system (pesco-ncr).
|
|||
|
|
|
||
|
|
An NCR number reads NCR-YYYY-NNNN (NCR-2026-0021). Q.C. gives one on a packet reject and on a rejected ITP line.
|
||
|
|
"""
|
||
|
|
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
import re
|
||
|
|
from typing import Any
|
||
|
|
|
||
|
|
from ..api.errors import ApiError
|
||
|
|
from ..text import LIMITS, clean_text
|
||
|
|
|
||
|
|
RX_NCR = re.compile(r"^NCR-\d{4}-\d{4}$")
|
||
|
|
NCR_URL = "https://ncr.pescoinc.biz/ncrs/"
|
||
|
|
MSG_INVALID = "Enter an NCR number like NCR-2026-0021."
|
||
|
|
NCR_MAX = LIMITS["ncr"]
|
||
|
|
|
||
|
|
|
||
|
|
def validate_ncr(text: Any) -> str:
|
||
|
|
"""The normalised NCR number (trimmed, upper case), or 422 invalid_ncr.
|
||
|
|
|
||
|
|
This is the hook for checking the number against pesco-ncr, which is a later phase. Today it accepts any
|
||
|
|
well-formed number and does not look it up.
|
||
|
|
"""
|
||
|
|
value = clean_text(text, NCR_MAX).upper()
|
||
|
|
if not RX_NCR.match(value):
|
||
|
|
raise ApiError(422, "invalid_ncr", MSG_INVALID)
|
||
|
|
return value
|
||
|
|
|
||
|
|
|
||
|
|
def ncr_url(number: str) -> str:
|
||
|
|
"""The pesco-ncr page of an NCR number."""
|
||
|
|
return NCR_URL + number
|