def get_generated_number(context, config, variables, **kw): """Generate a new persistent number with the number generator for the sequence type "Generated" """ # separator where to split the ID separator = kw.get('separator', '-') # allow portal_type override portal_type = kw.get("portal_type") or api.get_portal_type(context) # The ID format for string interpolation, e.g. WS-{seq:03d} id_template = config.get("form", "") # The split length defines where the variable part of the ID template begins split_length = config.get("split_length", 1) # The prefix tempalte is the static part of the ID prefix_template = slice(id_template, separator=separator, end=split_length) # get the number generator number_generator = getUtility(INumberGenerator) # generate the key for the number generator storage prefix = prefix_template.format(**variables) # normalize out any unicode characters like Ö, É, etc. from the prefix prefix = api.normalize_filename(prefix) # The key used for the storage key = make_storage_key(portal_type, prefix) # Handle flushed storage if key not in number_generator: max_num = 0 existing = get_ids_with_prefix(portal_type, prefix) numbers = map( lambda id: get_seq_number_from_id(id, id_template, prefix), existing) # figure out the highest number in the sequence if numbers: max_num = max(numbers) # set the number generator logger.info("*** SEEDING Prefix '{}' to {}".format(prefix, max_num)) number_generator.set_number(key, max_num) if not kw.get("dry_run", False): # Generate a new number # NOTE Even when the number exceeds the given ID sequence format, # it will overflow gracefully, e.g. # >>> {sampleId}-R{seq:03d}'.format(sampleId="Water", seq=999999) # 'Water-R999999‘ number = number_generator.generate_number(key=key) else: # => This allows us to "preview" the next generated ID in the UI # TODO Show the user the next generated number somewhere in the UI number = number_generator.get(key, 1) # Return an int or Alphanumber return get_alpha_or_number(number, id_template)
def get_generated_number(context, config, variables, **kw): """Generate a new persistent number with the number generator for the sequence type "Generated" """ # separator where to split the ID separator = kw.get('separator', '-') # allow portal_type override portal_type = kw.get("portal_type") or api.get_portal_type(context) # The ID format for string interpolation, e.g. WS-{seq:03d} id_template = config.get("form", "") # The split length defines where the variable part of the ID template begins split_length = config.get("split_length", 1) # The prefix tempalte is the static part of the ID prefix_template = slice(id_template, separator=separator, end=split_length) # get the number generator number_generator = getUtility(INumberGenerator) # generate the key for the number generator storage prefix = prefix_template.format(**variables) # normalize out any unicode characters like Ö, É, etc. from the prefix prefix = api.normalize_filename(prefix) # The key used for the storage key = make_storage_key(portal_type, prefix) # Handle flushed storage if key not in number_generator: max_num = 0 existing = get_ids_with_prefix(portal_type, prefix) numbers = map(lambda id: get_seq_number_from_id(id, id_template, prefix), existing) # figure out the highest number in the sequence if numbers: max_num = max(numbers) # set the number generator logger.info("*** SEEDING Prefix '{}' to {}".format(prefix, max_num)) number_generator.set_number(key, max_num) if not kw.get("dry_run", False): # Generate a new number # NOTE Even when the number exceeds the given ID sequence format, # it will overflow gracefully, e.g. # >>> {sampleId}-R{seq:03d}'.format(sampleId="Water", seq=999999) # 'Water-R999999‘ number = number_generator.generate_number(key=key) else: # => This allows us to "preview" the next generated ID in the UI # TODO Show the user the next generated number somewhere in the UI number = number_generator.get(key, 1) return number
def get_generated_number(context, config, variables, **kw): """Generate a new persistent number with the number generator for the sequence type "Generated" """ # separator where to split the ID separator = kw.get('separator', '-') # allow portal_type override portal_type = get_type_id(context, **kw) # The ID format for string interpolation, e.g. WS-{seq:03d} id_template = config.get("form", "") # The split length defines where the key is splitted from the value split_length = config.get("split_length", 1) # The prefix template is the static part of the ID prefix_template = slice(id_template, separator=separator, end=split_length) # get the number generator number_generator = getUtility(INumberGenerator) # generate the key for the number generator storage prefix = prefix_template.format(**variables) # normalize out any unicode characters like Ö, É, etc. from the prefix prefix = api.normalize_filename(prefix) # The key used for the storage key = make_storage_key(portal_type, prefix) if not kw.get("dry_run", False): # Generate a new number # NOTE Even when the number exceeds the given ID sequence format, # it will overflow gracefully, e.g. # >>> {sampleId}-R{seq:03d}'.format(sampleId="Water", seq=999999) # 'Water-R999999‘ number = number_generator.generate_number(key=key) else: # => This allows us to "preview" the next generated ID in the UI # TODO Show the user the next generated number somewhere in the UI number = number_generator.get(key, 1) # Return an int or Alphanumber return get_alpha_or_number(number, id_template)
def generateUniqueId(context, **kw): """ Generate pretty content IDs. """ # get the config for this portal type from the system setup config = get_config(context, **kw) # get the variables map for later string interpolation variables = get_variables(context, **kw) # The new generatef sequence number number = 0 # get the sequence type from the global config sequence_type = config.get("sequence_type", "generated") # Sequence Type is "Counter", so we use the length of the backreferences or # contained objects of the evaluated "context" defined in the config if sequence_type == 'counter': number = get_counted_number(context, config, variables, **kw) # Sequence Type is "Generated", so the ID is constructed according to the # configured split length if sequence_type == 'generated': number = get_generated_number(context, config, variables, **kw) # store the new sequence number to the variables map for string interpolation variables["seq"] = number # The ID formatting template from the user config, e.g. {sampleId}-R{seq:02d} id_template = config.get("form", "") # Interpolate the ID template new_id = id_template.format(**variables) normalized_id = api.normalize_filename(new_id) logger.info("generateUniqueId: {}".format(normalized_id)) return normalized_id
# store the new sequence number to the variables map for str interpolation if isinstance(number, Alphanumber): variables["alpha"] = number variables["seq"] = to_int(number) # The ID formatting template from user config, e.g. {sampleId}-R{seq:02d} id_template = config.get("form", "") # Interpolate the ID template try: new_id = id_template.format(**variables) except KeyError, e: logger.error('KeyError: {} not in id_template {}'.format( e, id_template)) raise normalized_id = api.normalize_filename(new_id) logger.info("generateUniqueId: {}".format(normalized_id)) return normalized_id def renameAfterCreation(obj): """Rename the content after it was created/added """ # Can't rename without a subtransaction commit when using portal_factory transaction.savepoint(optimistic=True) # The id returned should be normalized already new_id = None # Checking if an adapter exists for this content type. If yes, we will
number = get_generated_number(context, config, variables, **kw) # store the new sequence number to the variables map for str interpolation variables["seq"] = number # The ID formatting template from user config, e.g. {sampleId}-R{seq:02d} id_template = config.get("form", "") # Interpolate the ID template try: new_id = id_template.format(**variables) except KeyError, e: logger.error('KeyError: {} not in id_template {}'.format( e, id_template)) raise normalized_id = api.normalize_filename(new_id) logger.info("generateUniqueId: {}".format(normalized_id)) return normalized_id def renameAfterCreation(obj): """Rename the content after it was created/added """ # Check if the _bika_id was already set bika_id = getattr(obj, "_bika_id", None) if bika_id is not None: return bika_id # Can't rename without a subtransaction commit when using portal_factory transaction.savepoint(optimistic=True) # The id returned should be normalized already
def generateUniqueId(context, parent=False, portal_type=''): """ Generate pretty content IDs. """ if portal_type == '': portal_type = context.portal_type def getLastCounter(context, config): if config.get('counter_type', '') == 'backreference': return len(context.getBackReferences(config['counter_reference'])) - 1 elif config.get('counter_type', '') == 'contained': return len(context.objectItems(config['counter_reference'])) - 1 else: raise RuntimeError('ID Server: missing values in configuration') number_generator = getUtility(INumberGenerator) # keys = number_generator.keys() # values = number_generator.values() # for i in range(len(keys)): # print '%s : %s' % (keys[i], values[i]) def getConfigByPortalType(config_map, portal_type): config = {} for c in config_map: if c['portal_type'] == portal_type: config = c break return config config_map = api.get_bika_setup().getIDFormatting() config = getConfigByPortalType( config_map=config_map, portal_type=portal_type) if portal_type == "AnalysisRequest": variables_map = { 'sampleId': context.getSample().getId(), 'sample': context.getSample(), 'year': DateTime().strftime("%Y")[2:], } elif portal_type == "SamplePartition": variables_map = { 'sampleId': context.aq_parent.getId(), 'sample': context.aq_parent, 'year': DateTime().strftime("%Y")[2:], } elif portal_type == "Sample" and parent: config = getConfigByPortalType( config_map=config_map, portal_type='SamplePartition') # Override variables_map = { 'sampleId': context.getId(), 'sample': context, 'year': DateTime().strftime("%Y")[2:], } elif portal_type == "Sample": sampleDate = None sampleType = context.getSampleType().getPrefix() if context.getSamplingDate(): sampleDate = DT2dt(context.getSamplingDate()) variables_map = { 'clientId': context.aq_parent.getClientID(), 'sampleDate': sampleDate, 'sampleType': api.normalize_filename(sampleType), 'year': DateTime().strftime("%Y")[2:], } else: if not config: # Provide default if no format specified on bika_setup config = { 'form': '%s-{seq}' % portal_type.lower(), 'sequence_type': 'generated', 'prefix': '%s' % portal_type.lower(), } variables_map = { 'year': DateTime().strftime("%Y")[2:], } # Actual id construction starts here form = config['form'] if config['sequence_type'] == 'counter': new_seq = getLastCounter( context=variables_map[config['context']], config=config) elif config['sequence_type'] == 'generated': try: if config.get('split_length', None) == 0: prefix_config = '-'.join(form.split('-')[:-1]) prefix = prefix_config.format(**variables_map) elif config.get('split_length', None) > 0: prefix_config = '-'.join(form.split('-')[:config['split_length']]) prefix = prefix_config.format(**variables_map) else: prefix = config['prefix'] new_seq = number_generator(key=prefix) except KeyError, e: msg = "KeyError in GenerateUniqueId on %s: %s" % ( str(config), e) raise RuntimeError(msg)