Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expand Auto-Numbering Functionality for Catalog Numbers #5234

Closed
grantfitzsimmons opened this issue Aug 16, 2024 · 1 comment
Closed

Expand Auto-Numbering Functionality for Catalog Numbers #5234

grantfitzsimmons opened this issue Aug 16, 2024 · 1 comment
Assignees
Labels
1 - Request A request made by a member of the community geospecify

Comments

@grantfitzsimmons
Copy link
Member

Description:
Enhance the auto-numbering system to allow for more complex numbering schemes, including the ability to incorporate prefixes and suffixes while maintaining unique identifiers.

Acceptance Criteria:

  • Allow users to define auto-numbering patterns that include prefixes and suffixes.

@realVinayak demonstrated that you can (mis)use the byyear numbering system to have an auto-incrementing system based on a generic prefix:

<format system="false" name="OSU CE Number Regexp" class="edu.ku.brc.specify.datamodel.CollectingEvent" fieldname="stationFieldNumber" default="true">
<autonumber>edu.ku.brc.af.core.db.AutoNumberGeneric</autonumber>
<field type="regex" size="4" value="[-|0-9]{4}" byyear="true"/>
<field type="constant" size="1" value=":"/>
<field type="numeric" size="4" inc="true"/>
</format>
  • Ensure that auto-incrementing can be based on the prefix without breaking existing functionality.
  • Provide clear documentation on how to set up and use the expanded auto-numbering features.
@grantfitzsimmons grantfitzsimmons added 1 - Request A request made by a member of the community geospecify labels Aug 16, 2024
@melton-jason
Copy link
Contributor

melton-jason commented Nov 19, 2024

Correct me if I'm wrong or misunderstanding the requirement, but isn't this functionality already present in Specify?

Screen.Recording.2024-11-19.at.11.40.51.AM.mov
  <format system="false" name="PrefixedCatalogNumber" class="edu.ku.brc.specify.datamodel.CollectionObject" fieldname="catalogNumber">
    <field type="regex" size="3" minsize="3" value="[A-Z]{3}" pattern="AAA"/>
    <field type="separator" size="1" value="-"/>
    <field type="numeric" size="6" inc="true"/>
  </format>

(There's currently a bug in where the pattern isn't being inserted into the form, but you can still see the behavior of auto-incrementing)

If the prefix/suffix is static, you can use a constant field instead for the same effect:

  <format system="false" name="GeoCatalogNumber" class="edu.ku.brc.specify.datamodel.CollectionObject" fieldname="catalogNumber">
    <field type="constant" size="3" value="MIN"/>
    <field type="separator" size="1" value="-"/>
    <field type="numeric" size="6" inc="true"/>
  </format>

The incrementing numeric field will match against other records which have the same prefix/suffix

def _autonumber_queryset(self, collection, model, fieldname: str, with_year: List[str]):
group_filter = get_autonumber_group_filter(model, collection, self.format_name)
objs = model.objects.filter(**{ fieldname + '__regex': self.autonumber_regexp(with_year) })
return group_filter(objs).order_by('-' + fieldname)

def autonumber_regexp(self, vals: Sequence[str]) -> str:
return '^{}$'.format(''.join(
'({})'.format(field.value_regexp() if field.is_wild(val) else re.escape(val))
for field, val in zip(self.fields, vals)
))

class Field(NamedTuple):
size: int
value: str
inc: bool
by_year: bool
def can_autonumber(self) -> bool:
return self.inc or self.by_year
def wild_regexp(self) -> str:
return re.escape(self.value)
def value_regexp(self) -> str:
return self.wild_regexp()
def is_wild(self, value: str) -> bool:
logger.debug("%s checking if value %s is wild", self, value)
return bool(re.match("^%s$" % self.wild_regexp(), value) and not
re.match("^%s$" % self.value_regexp(), value))
def wild_or_value_regexp(self) -> str:
if self.can_autonumber():
return '%s|%s' % (self.wild_regexp(), self.value_regexp())
else:
return self.value_regexp()
def canonicalize(self, value: str) -> str:
return value
class NumericField(Field):
def __new__(cls, size, value=None, inc=False, by_year=False):
value = size * '#'
return Field.__new__(cls, size, value, inc, by_year)
def value_regexp(self) -> str:
return r'[0-9]{%d}' % self.size
class YearField(Field):
def value_regexp(self) -> str:
return r'[0-9]{%d}' % self.size
class AlphaNumField(Field):
def value_regexp(self) -> str:
return r'[a-zA-Z0-9]{%d}' % self.size
class AnyCharField(Field):
def value_regexp(self) -> str:
return r'.{%d}' % self.size
class RegexField(Field):
def value_regexp(self) -> str:
return self.value
class AlphaField(Field):
def value_regexp(self) -> str:
return r'[a-zA-Z]{%d}' % self.size
class ConstantField(Field):
def is_wild(self, value: str) -> bool:
return False
def value_regexp(self) -> str:
return self.wild_regexp()
class SeparatorField(Field):
def is_wild(self, value: str) -> bool:
return False
def value_regexp(self) -> str:
return self.wild_regexp()
class CNNField(NumericField):
def __new__(cls):
return NumericField.__new__(cls, size=9, inc=9)
def value_regexp(self) -> str:
return r'[0-9]{0,%d}' % self.size
def canonicalize(self, value: str) -> str:
return value.zfill(self.size)

@melton-jason melton-jason self-assigned this Nov 19, 2024
@specify specify locked and limited conversation to collaborators Dec 20, 2024
@grantfitzsimmons grantfitzsimmons converted this issue into discussion #5981 Dec 20, 2024

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
1 - Request A request made by a member of the community geospecify
Projects
None yet
Development

No branches or pull requests

2 participants