Merge branch 'master' into feature/RED-10342

# Conflicts:
#	persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/FileAttributeConfigPersistenceService.java
#	persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/FileAttributeTest.java
This commit is contained in:
corinaolariu 2024-12-06 10:04:35 +02:00
commit fac80bbc5c
18 changed files with 259 additions and 56 deletions

View File

@ -357,9 +357,9 @@ public class DictionaryController implements DictionaryResource {
public void changeFlags(@PathVariable(TYPE_PARAMETER_NAME) String type,
@PathVariable(DOSSIER_TEMPLATE_PARAMETER_NAME) String dossierTemplateId,
@PathVariable(value = DOSSIER_ID_PARAMETER_NAME) String dossierId,
@RequestParam(value = "addToDictionary") boolean addToDictionary) {
@RequestParam(value = "addToDictionaryAction") boolean addToDictionaryAction) {
dictionaryService.changeAddToDictionary(type, dossierTemplateId, dossierId, addToDictionary);
dictionaryService.changeAddToDictionary(type, dossierTemplateId, dossierId, addToDictionaryAction);
}

View File

@ -17,6 +17,7 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.DossierPersistenceService;
import com.iqser.red.service.persistence.management.v1.processor.utils.DossierAttributeConfigMapper;
import com.knecon.fforesight.keycloakcommons.security.KeycloakSecurity;
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.DossierAttributeConfigEntity;
import com.iqser.red.service.persistence.management.v1.processor.service.AccessControlService;
@ -52,7 +53,7 @@ public class DossierAttributesController implements DossierAttributesResource {
var result = MagicConverter.convert(dossierAttributeConfigPersistenceService.setDossierAttributesConfig(dossierTemplateId,
MagicConverter.convert(dossierAttributesConfig.getDossierAttributeConfigs(),
DossierAttributeConfigEntity.class)),
DossierAttributeConfig.class);
DossierAttributeConfig.class, new DossierAttributeConfigMapper());
auditPersistenceService.insertRecord(AuditRequest.builder()
.userId(KeycloakSecurity.getUserId())
.objectId(dossierTemplateId)
@ -72,7 +73,7 @@ public class DossierAttributesController implements DossierAttributesResource {
var result = MagicConverter.convert(dossierAttributeConfigPersistenceService.addOrUpdateDossierAttribute(dossierTemplateId,
MagicConverter.convert(dossierAttribute,
DossierAttributeConfigEntity.class)),
DossierAttributeConfig.class);
DossierAttributeConfig.class, new DossierAttributeConfigMapper());
auditPersistenceService.insertRecord(AuditRequest.builder()
.userId(KeycloakSecurity.getUserId())
.objectId(dossierTemplateId)
@ -118,7 +119,7 @@ public class DossierAttributesController implements DossierAttributesResource {
public DossierAttributesConfig getDossierAttributesConfig(@PathVariable(DOSSIER_TEMPLATE_ID) String dossierTemplateId) {
var result = dossierAttributeConfigPersistenceService.getDossierAttributes(dossierTemplateId);
return new DossierAttributesConfig(MagicConverter.convert(result, DossierAttributeConfig.class));
return new DossierAttributesConfig(MagicConverter.convert(result, DossierAttributeConfig.class, new DossierAttributeConfigMapper()));
}

View File

@ -15,6 +15,7 @@ import org.springframework.web.bind.annotation.RestController;
import com.iqser.red.service.persistence.management.v1.processor.model.websocket.FileEventType;
import com.iqser.red.service.persistence.management.v1.processor.service.websocket.WebsocketService;
import com.iqser.red.service.persistence.management.v1.processor.utils.FileAttributeConfigMapper;
import com.knecon.fforesight.keycloakcommons.security.KeycloakSecurity;
import com.iqser.red.service.persistence.management.v1.processor.entity.configuration.FileAttributesGeneralConfigurationEntity;
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.FileAttributeConfigEntity;
@ -74,7 +75,9 @@ public class FileAttributesController implements FileAttributesResource {
.filenameMappingColumnHeaderName(fileAttributesConfig.getFilenameMappingColumnHeaderName())
.delimiter(fileAttributesConfig.getDelimiter())
.encoding(fileAttributesConfig.getEncoding())
.fileAttributeConfigs(MagicConverter.convert(fileAttributeConfigPersistenceService.getFileAttributes(dossierTemplateId), FileAttributeConfig.class))
.fileAttributeConfigs(MagicConverter.convert(fileAttributeConfigPersistenceService.getFileAttributes(dossierTemplateId),
FileAttributeConfig.class,
new FileAttributeConfigMapper()))
.build();
}
@ -96,7 +99,7 @@ public class FileAttributesController implements FileAttributesResource {
dossierTemplateId))
.build());
return MagicConverter.convert(result, FileAttributeConfig.class);
return MagicConverter.convert(result, FileAttributeConfig.class, new FileAttributeConfigMapper());
}
@ -145,7 +148,7 @@ public class FileAttributesController implements FileAttributesResource {
.filenameMappingColumnHeaderName(generalConfig.getFilenameMappingColumnHeaderName())
.delimiter(generalConfig.getDelimiter())
.encoding(generalConfig.getEncoding())
.fileAttributeConfigs(MagicConverter.convert(fileAttributeConfigs, FileAttributeConfig.class))
.fileAttributeConfigs(MagicConverter.convert(fileAttributeConfigs, FileAttributeConfig.class, new FileAttributeConfigMapper()))
.build();
}

View File

@ -223,7 +223,7 @@ public interface DictionaryResource {
void changeFlags(@PathVariable(TYPE_PARAMETER_NAME) String type,
@PathVariable(DOSSIER_TEMPLATE_PARAMETER_NAME) String dossierTemplateId,
@PathVariable(DOSSIER_ID_PARAMETER_NAME) String dossierId,
@RequestParam(value = "addToDictionary") boolean addToDictionary);
@RequestParam(value = "addToDictionaryAction") boolean addToDictionaryAction);
@PostMapping(value = DICTIONARY_REST_PATH + DIFFERENCE + DOSSIER_TEMPLATE_PATH_VARIABLE, consumes = MediaType.APPLICATION_JSON_VALUE)

View File

@ -10,6 +10,7 @@ import org.springframework.web.bind.annotation.RestController;
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.DossierAttributeConfigEntity;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.DossierAttributeConfigPersistenceService;
import com.iqser.red.service.persistence.management.v1.processor.utils.DossierAttributeConfigMapper;
import com.iqser.red.service.persistence.service.v1.api.internal.resources.DossierAttributesConfigResource;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.DossierAttributeConfig;
@ -27,7 +28,7 @@ public class DossierAttributesConfigInternalController implements DossierAttribu
@Override
public List<DossierAttributeConfig> getDossierAttributes(@PathVariable(DOSSIER_TEMPLATE_ID) String dossierTemplateId) {
return convert(dossierAttributeConfigPersistenceService.getDossierAttributes(dossierTemplateId), DossierAttributeConfig.class);
return convert(dossierAttributeConfigPersistenceService.getDossierAttributes(dossierTemplateId), DossierAttributeConfig.class, new DossierAttributeConfigMapper());
}
}

View File

@ -8,6 +8,7 @@ import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.FileAttributeConfigPersistenceService;
import com.iqser.red.service.persistence.management.v1.processor.utils.FileAttributeConfigMapper;
import com.iqser.red.service.persistence.service.v1.api.internal.resources.FileAttributesConfigResource;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileAttributeConfig;
@ -25,7 +26,7 @@ public class FileAttributesConfigInternalController implements FileAttributesCon
@Override
public List<FileAttributeConfig> getFileAttributeConfigs(@PathVariable(DOSSIER_TEMPLATE_ID) String dossierTemplateId) {
return convert(fileAttributeConfigPersistenceService.getFileAttributes(dossierTemplateId), FileAttributeConfig.class);
return convert(fileAttributeConfigPersistenceService.getFileAttributes(dossierTemplateId), FileAttributeConfig.class, new FileAttributeConfigMapper());
}
}

View File

@ -53,6 +53,8 @@ import com.iqser.red.service.persistence.management.v1.processor.service.persist
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.LegalBasisMappingPersistenceService;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.ReportTemplatePersistenceService;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.RulesPersistenceService;
import com.iqser.red.service.persistence.management.v1.processor.utils.DossierAttributeConfigMapper;
import com.iqser.red.service.persistence.management.v1.processor.utils.FileAttributeConfigMapper;
import com.iqser.red.service.persistence.management.v1.processor.utils.FileSystemBackedArchiver;
import com.iqser.red.service.persistence.management.v1.processor.utils.StorageIdUtils;
import com.iqser.red.service.persistence.service.v1.api.shared.model.RuleFileType;
@ -183,13 +185,16 @@ public class DossierTemplateExportService {
fileSystemBackedArchiver.addEntries(new FileSystemBackedArchiver.ArchiveModel(folder,
getFilename(ExportFilename.DOSSIER_ATTRIBUTES_CONFIG, JSON_EXT),
objectMapper.writeValueAsBytes(convert(dossierAttributesConfig,
DossierAttributeConfig.class))));
DossierAttributeConfig.class,
new DossierAttributeConfigMapper()))));
// add file attribute configs
List<FileAttributeConfigEntity> fileAttributeConfigList = fileAttributeConfigPersistenceService.getFileAttributes(dossierTemplate.getId());
fileSystemBackedArchiver.addEntries(new FileSystemBackedArchiver.ArchiveModel(folder,
getFilename(ExportFilename.FILE_ATTRIBUTE_CONFIG, JSON_EXT),
objectMapper.writeValueAsBytes(convert(fileAttributeConfigList, FileAttributeConfig.class))));
objectMapper.writeValueAsBytes(convert(fileAttributeConfigList,
FileAttributeConfig.class,
new FileAttributeConfigMapper()))));
// add legal basis mapping
List<LegalBasisEntity> legalBasisMappingList = legalBasisMappingPersistenceService.getLegalBasisMapping(dossierTemplate.getId());

View File

@ -494,9 +494,9 @@ public class DictionaryService {
}
@PreAuthorize("hasAuthority('" + ADD_UPDATE_DICTIONARY_TYPE + "')")
public void changeAddToDictionary(String type, String dossierTemplateId, String dossierId, boolean addToDictionary) {
public void changeAddToDictionary(String type, String dossierTemplateId, String dossierId, boolean addToDictionaryAction) {
dictionaryPersistenceService.updateAddToDictionary(toTypeId(type, dossierTemplateId, dossierId), addToDictionary);
dictionaryPersistenceService.updateAddToDictionary(toTypeId(type, dossierTemplateId, dossierId), addToDictionaryAction);
}

View File

@ -25,6 +25,7 @@ import com.iqser.red.service.persistence.management.v1.processor.service.persist
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.DossierPersistenceService;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.LegalBasisMappingPersistenceService;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.RulesPersistenceService;
import com.iqser.red.service.persistence.management.v1.processor.settings.FileManagementServiceSettings;
import com.iqser.red.service.persistence.service.v1.api.shared.model.RuleFileType;
import com.iqser.red.service.persistence.service.v1.api.shared.model.component.ComponentMappingMetadata;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.ErrorCode;
@ -50,6 +51,7 @@ public class ReanalysisRequiredStatusService {
DossierPersistenceService dossierPersistenceService;
LegalBasisMappingPersistenceService legalBasisMappingPersistenceService;
ComponentMappingService componentMappingService;
FileManagementServiceSettings settings;
public FileModel enhanceFileStatusWithAnalysisRequirements(FileModel fileModel) {
@ -65,7 +67,12 @@ public class ReanalysisRequiredStatusService {
Map<String, DossierEntity> dossierMap = new HashMap<>();
Map<String, Map<String, Integer>> componentMappingVersionMap = new HashMap<>();
fileModels.forEach(entry -> {
var analysisRequiredResult = computeAnalysisRequired(entry, ignoreProcessingStates, dossierTemplateVersionMap, dossierVersionMap, dossierMap, componentMappingVersionMap);
var analysisRequiredResult = computeAnalysisRequired(entry,
ignoreProcessingStates,
dossierTemplateVersionMap,
dossierVersionMap,
dossierMap,
componentMappingVersionMap);
entry.setReanalysisRequired(analysisRequiredResult.isReanalysisRequired());
entry.setFullAnalysisRequired(analysisRequiredResult.isFullAnalysisRequired());
entry.setComponentReanalysisRequired(analysisRequiredResult.isComponentReanalysisRequired());
@ -123,7 +130,7 @@ public class ReanalysisRequiredStatusService {
if (fileStatus.getLastFileAttributeChange() != null && fileStatus.getLastProcessed().isBefore(fileStatus.getLastFileAttributeChange())) {
return new AnalysisRequiredResult(true, false);
} else {
return requiresReanalysisBasedOnVersionDifference(fileStatus, dossier, dossierTemplateVersionMap, dossierVersionMap,componentMappingVersionMap);
return requiresReanalysisBasedOnVersionDifference(fileStatus, dossier, dossierTemplateVersionMap, dossierVersionMap, componentMappingVersionMap);
}
default:
return new AnalysisRequiredResult(false, false);
@ -134,14 +141,18 @@ public class ReanalysisRequiredStatusService {
}
private AnalysisRequiredResult computeAnalysisRequiredForErrorState(DossierEntity dossier,FileModel fileStatus, Map<String, Map<VersionType, Long>> dossierTemplateVersionMap){
private AnalysisRequiredResult computeAnalysisRequiredForErrorState(DossierEntity dossier,
FileModel fileStatus,
Map<String, Map<VersionType, Long>> dossierTemplateVersionMap) {
Map<VersionType, Long> dossierTemplateVersions = dossierTemplateVersionMap.computeIfAbsent(dossier.getDossierTemplateId(),
k -> buildVersionData(dossier.getDossierTemplateId()));
var rulesVersionMatches = fileStatus.getRulesVersion() == dossierTemplateVersions.getOrDefault(RULES, -1L);
var componentRulesVersionMatches = fileStatus.getComponentRulesVersion() == dossierTemplateVersions.getOrDefault(COMPONENT_RULES, -1L);
var isRuleExecutionTimeout = fileStatus.getFileErrorInfo() != null && fileStatus.getFileErrorInfo().getErrorCode() != null && fileStatus.getFileErrorInfo().getErrorCode().equals(
ErrorCode.RULES_EXECUTION_TIMEOUT);
var isRuleExecutionTimeout = fileStatus.getFileErrorInfo() != null && fileStatus.getFileErrorInfo().getErrorCode() != null && fileStatus.getFileErrorInfo()
.getErrorCode()
.equals(ErrorCode.RULES_EXECUTION_TIMEOUT);
var fullAnalysisRequired = (!rulesVersionMatches || !componentRulesVersionMatches) && !isRuleExecutionTimeout;
@ -153,7 +164,7 @@ public class ReanalysisRequiredStatusService {
DossierEntity dossier,
Map<String, Map<VersionType, Long>> dossierTemplateVersionMap,
Map<String, Long> dossierVersionMap,
Map<String, Map<String,Integer>> componentMappingVersionMap) {
Map<String, Map<String, Integer>> componentMappingVersionMap) {
// get relevant versions
Map<VersionType, Long> dossierTemplateVersions = dossierTemplateVersionMap.computeIfAbsent(dossier.getDossierTemplateId(),
@ -162,7 +173,8 @@ public class ReanalysisRequiredStatusService {
Map<String, Integer> componentMappingVersions = componentMappingVersionMap.computeIfAbsent(dossier.getDossierTemplateId(),
k -> componentMappingService.getMetaDataByDossierTemplateId(dossier.getDossierTemplateId())
.stream()
.collect(Collectors.toMap(ComponentMappingMetadata::getName, ComponentMappingMetadata::getVersion)));
.collect(Collectors.toMap(ComponentMappingMetadata::getName,
ComponentMappingMetadata::getVersion)));
Long dossierDictionaryVersion = dossierVersionMap.computeIfAbsent(fileStatus.getDossierId(), k -> getDossierVersionData(fileStatus.getDossierId()));
@ -177,22 +189,23 @@ public class ReanalysisRequiredStatusService {
var dossierDictionaryVersionMatches = Math.max(fileStatus.getDossierDictionaryVersion(), 0) == dossierDictionaryVersion;
var reanalysisRequired = !dictionaryVersionMatches || !dossierDictionaryVersionMatches || !mappingVersionAllMatch;
var fullAnalysisRequired = !rulesVersionMatches || !componentRulesVersionMatches || !legalBasisVersionMatches || !aiVersionMatches;
var fullAnalysisRequired = !rulesVersionMatches || !componentRulesVersionMatches || !legalBasisVersionMatches || (settings.isLlmNerServiceEnabled() && !aiVersionMatches);
var componentReanalysisRequired = !dateFormatsVersionMatches;
if (reanalysisRequired || fullAnalysisRequired || componentReanalysisRequired) {
log.debug(buildMessage(fileStatus,
rulesVersionMatches,
dossierTemplateVersions,
componentRulesVersionMatches,
dateFormatsVersionMatches,
dictionaryVersionMatches,
legalBasisVersionMatches,
dossierDictionaryVersionMatches,
dossierDictionaryVersion,
mappingVersionAllMatch,
componentMappingVersions));
rulesVersionMatches,
dossierTemplateVersions,
componentRulesVersionMatches,
dateFormatsVersionMatches,
dictionaryVersionMatches,
legalBasisVersionMatches,
dossierDictionaryVersionMatches,
dossierDictionaryVersion,
mappingVersionAllMatch,
componentMappingVersions,
aiVersionMatches));
}
return new AnalysisRequiredResult(reanalysisRequired, fullAnalysisRequired, componentReanalysisRequired);
@ -202,14 +215,15 @@ public class ReanalysisRequiredStatusService {
private String buildMessage(FileModel fileStatus,
boolean rulesVersionMatches,
Map<VersionType, Long> dossierTemplateVersions,
boolean versionMatches,
boolean componentRulesVersionMatches,
boolean dateFormatsVersionMatches,
boolean dictionaryVersionMatches,
boolean legalBasisVersionMatches,
boolean dossierDictionaryVersionMatches,
Long dossierDictionaryVersion,
boolean mappingVersionAllMatch,
Map<String, Integer> componentMappingVersions) {
Map<String, Integer> componentMappingVersions,
boolean aiVersionMatches) {
StringBuilder messageBuilder = new StringBuilder();
messageBuilder.append("For file: ").append(fileStatus.getId()).append("-").append(fileStatus.getFilename()).append(" analysis is required because -> ");
@ -264,6 +278,21 @@ public class ReanalysisRequiredStatusService {
needComma = true;
}
if (!dateFormatsVersionMatches) {
if (needComma) {
messageBuilder.append(", ");
}
messageBuilder.append("dateFormatsVersions: ").append(fileStatus.getDateFormatsVersion()).append("/").append(dossierTemplateVersions.getOrDefault(DATE_FORMATS, -1L));
needComma = true;
}
if (settings.isLlmNerServiceEnabled() && !aiVersionMatches) {
if (needComma) {
messageBuilder.append(", ");
}
messageBuilder.append("aiVersions: ").append(fileStatus.getAiCreationVersion()).append("/").append(dossierTemplateVersions.getOrDefault(AI_CREATION, 0L));
}
return messageBuilder.toString();
}

View File

@ -12,6 +12,7 @@ import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import com.iqser.red.service.persistence.management.v1.processor.entity.configuration.TypeEntity;
import com.iqser.red.service.persistence.management.v1.processor.exception.BadRequestException;
import com.iqser.red.service.persistence.management.v1.processor.exception.ConflictException;
import com.iqser.red.service.persistence.management.v1.processor.exception.NotFoundException;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.DossierRepository;
@ -357,12 +358,14 @@ public class DictionaryPersistenceService {
@Transactional
public void updateAddToDictionary(String typeId, boolean addToDictionary) {
public void updateAddToDictionary(String typeId, boolean addToDictionaryAction) {
var typeEntity = getType(typeId);
if (typeEntity.isDossierDictionaryOnly()) {
typeEntity.setAddToDictionaryAction(addToDictionary);
typeEntity.setAddToDictionaryAction(addToDictionaryAction);
typeRepository.saveAndFlush(typeEntity);
} else {
throw new BadRequestException("The addToDictionaryAction flag can only be adjusted for dossierDictionaryOnly-types.");
}
}

View File

@ -60,7 +60,7 @@ public class DossierAttributeConfigPersistenceService {
dossierAttributeConfig.setDossierTemplate(dossierTemplate);
if (dossierAttributeConfig.getId() == null) {
dossierAttributeConfig.setId(UUID.randomUUID().toString());
setPlaceholder(dossierAttributeConfig);
checkAndSetPlaceholder(dossierAttributeConfig);
uniqueLabelAndPlaceholder(dossierAttributeConfig);
return dossierAttributeConfigRepository.save(dossierAttributeConfig);
} else {
@ -74,12 +74,13 @@ public class DossierAttributeConfigPersistenceService {
config.setEditable(dossierAttributeConfig.isEditable());
config.setDisplayedInDossierList(dossierAttributeConfig.isDisplayedInDossierList());
config.setFilterable(dossierAttributeConfig.isFilterable());
setPlaceholder(config);
checkAndSetPlaceholder(dossierAttributeConfig);
config.setPlaceholder(dossierAttributeConfig.getPlaceholder());
uniqueLabelAndPlaceholder(dossierAttributeConfig);
return dossierAttributeConfigRepository.save(config);
} else {
dossierAttributeConfig.setId(UUID.randomUUID().toString());
setPlaceholder(dossierAttributeConfig);
checkAndSetPlaceholder(dossierAttributeConfig);
uniqueLabelAndPlaceholder(dossierAttributeConfig);
return dossierAttributeConfigRepository.save(dossierAttributeConfig);
}
@ -94,12 +95,25 @@ public class DossierAttributeConfigPersistenceService {
}
private void setPlaceholder(DossierAttributeConfigEntity dossierAttributeConfig) {
private void checkAndSetPlaceholder(DossierAttributeConfigEntity dossierAttributeConfig) {
String placeholder = "{{dossier.attribute." + StringUtils.remove(WordUtils.capitalizeFully(dossierAttributeConfig.getLabel(), ' '), " ") + "}}";
dossierAttributeConfig.setPlaceholder(placeholder);
if (StringUtils.isEmpty(dossierAttributeConfig.getPlaceholder())) {
String placeholder = "{{dossier.attribute." + StringUtils.remove(WordUtils.capitalizeFully(dossierAttributeConfig.getLabel(), ' '), " ") + "}}";
dossierAttributeConfig.setPlaceholder(placeholder);
} else {
uniquePlaceholder(dossierAttributeConfig);
}
}
private void uniquePlaceholder(DossierAttributeConfigEntity dossierAttributesConfig) {
getDossierAttributes(dossierAttributesConfig.getDossierTemplate().getId()).stream()
.filter(d -> !d.getId().equals(dossierAttributesConfig.getId()))
.forEach(other -> {
if (other.getPlaceholder().equalsIgnoreCase(dossierAttributesConfig.getPlaceholder())) {
throw new ConflictException("Placeholder already exists. " + dossierAttributesConfig.getPlaceholder());
}
});
}
private void uniqueLabelAndPlaceholder(DossierAttributeConfigEntity dossierAttributesConfig) {

View File

@ -115,7 +115,7 @@ public class FileAttributeConfigPersistenceService {
}
if (fileAttributeConfig.getId() == null) {
fileAttributeConfig.setId(UUID.randomUUID().toString());
setPlaceholder(fileAttributeConfig);
checkAndSetPlaceholder(fileAttributeConfig);
uniqueLabelAndPlaceholder(fileAttributeConfig);
return fileAttributeConfigRepository.save(fileAttributeConfig);
} else {
@ -132,12 +132,13 @@ public class FileAttributeConfigPersistenceService {
config.setPrimaryAttribute(fileAttributeConfig.isPrimaryAttribute());
config.setFilterable(fileAttributeConfig.isFilterable());
config.setIncludeInCsvExport(fileAttributeConfig.isIncludeInCsvExport());
setPlaceholder(config);
checkAndSetPlaceholder(fileAttributeConfig);
config.setPlaceholder(fileAttributeConfig.getPlaceholder());
uniqueLabelAndPlaceholder(fileAttributeConfig);
return fileAttributeConfigRepository.save(config);
} else {
fileAttributeConfig.setId(UUID.randomUUID().toString());
setPlaceholder(fileAttributeConfig);
checkAndSetPlaceholder(fileAttributeConfig);
uniqueLabelAndPlaceholder(fileAttributeConfig);
return fileAttributeConfigRepository.save(fileAttributeConfig);
}
@ -152,12 +153,25 @@ public class FileAttributeConfigPersistenceService {
}
private void setPlaceholder(FileAttributeConfigEntity fileAttributeConfig) {
private void checkAndSetPlaceholder(FileAttributeConfigEntity fileAttributeConfig) {
String placeholder = "{{file.attribute." + StringUtils.remove(WordUtils.capitalizeFully(fileAttributeConfig.getLabel(), ' '), " ") + "}}";
fileAttributeConfig.setPlaceholder(placeholder);
if (StringUtils.isEmpty(fileAttributeConfig.getPlaceholder())) {
String placeholder = "{{file.attribute." + StringUtils.remove(WordUtils.capitalizeFully(fileAttributeConfig.getLabel(), ' '), " ") + "}}";
fileAttributeConfig.setPlaceholder(placeholder);
} else {
uniquePlaceholder(fileAttributeConfig);
}
}
private void uniquePlaceholder(FileAttributeConfigEntity fileAttributeConfig) {
getFileAttributes(fileAttributeConfig.getDossierTemplate().getId()).stream()
.filter(d -> !d.getId().equals(fileAttributeConfig.getId()))
.forEach(other -> {
if (other.getPlaceholder().equalsIgnoreCase(fileAttributeConfig.getPlaceholder())) {
throw new ConflictException("Placeholder already exists.");
}
});
}
private void uniqueLabelAndPlaceholder(FileAttributeConfigEntity fileAttributeConfig) {

View File

@ -737,11 +737,14 @@ public class FileStatusPersistenceService {
fileRepository.setAiCreationVersion(fileId, aiCreationVersion);
}
public List<FileEntity> findAllByIds(Set<String> fileIds) {
return fileRepository.findAllById(fileIds);
}
public List<FileEntity> findAllDossierIdAndIds(String dossierId, Set<String> fileIds) {
return fileRepository.findAllDossierIdAndIds(dossierId, fileIds);

View File

@ -0,0 +1,16 @@
package com.iqser.red.service.persistence.management.v1.processor.utils;
import java.util.function.BiConsumer;
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.DossierAttributeConfigEntity;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.DossierAttributeConfig;
public class DossierAttributeConfigMapper implements BiConsumer<DossierAttributeConfigEntity, DossierAttributeConfig> {
@Override
public void accept(DossierAttributeConfigEntity dossierAttributeConfigEntity, DossierAttributeConfig dossierAttributeConfig) {
dossierAttributeConfig.setDossierTemplateId(dossierAttributeConfigEntity.getDossierTemplate().getId());
}
}

View File

@ -0,0 +1,16 @@
package com.iqser.red.service.persistence.management.v1.processor.utils;
import java.util.function.BiConsumer;
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.FileAttributeConfigEntity;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileAttributeConfig;
public class FileAttributeConfigMapper implements BiConsumer<FileAttributeConfigEntity, FileAttributeConfig> {
@Override
public void accept(FileAttributeConfigEntity fileAttributeConfigEntity, FileAttributeConfig fileAttributeConfig) {
fileAttributeConfig.setDossierTemplateId(fileAttributeConfigEntity.getDossierTemplate().getId());
}
}

View File

@ -1183,7 +1183,7 @@ public class DictionaryTest extends AbstractPersistenceServerServiceTest {
var type = dictionaryClient.addType(createTypeValue);
List<TypeValue> customTypes = dictionaryClient.getAllTypes(dossierTemplate.getId(), dossier.getId(), false).getTypes()
List<TypeValue> customTypes = dictionaryClient.getAllTypes(dossierTemplate.getId(), dossier.getId(), false).getTypes()
.stream()
.filter(t -> !t.isSystemManaged())
.toList();
@ -1213,7 +1213,7 @@ public class DictionaryTest extends AbstractPersistenceServerServiceTest {
@Test
void testRecreateTypeAndCheckMergedDictionary() {
void testRecreateTypeAndCheckMergedDictionary() {
var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();
var dossier = dossierTesterAndProvider.provideTestDossier(dossierTemplate, "TestDossier");
@ -1240,7 +1240,10 @@ public class DictionaryTest extends AbstractPersistenceServerServiceTest {
UpdateEntries updateEntries = new UpdateEntries(newDossierEntries, allEntries);
dictionaryClient.updateEntries(type.getType(), type.getDossierTemplateId(), updateEntries, dossier.getId(), DictionaryEntryType.ENTRY);
List<DictionaryEntryEntity> deleted = entryRepository.findAll().stream().filter(DictionaryEntryEntity::isDeleted).toList();
List<DictionaryEntryEntity> deleted = entryRepository.findAll()
.stream()
.filter(DictionaryEntryEntity::isDeleted)
.toList();
assertEquals(3, deleted.size());
var updatedDossierDictionary = dictionaryClient.getDictionaryForType(type.getType(), dossierTemplate.getId(), dossier.getId());
@ -1257,7 +1260,10 @@ public class DictionaryTest extends AbstractPersistenceServerServiceTest {
assertEquals(2, deletedType1Entities.size());
deleted = entryRepository.findAll().stream().filter(DictionaryEntryEntity::isDeleted).toList();
deleted = entryRepository.findAll()
.stream()
.filter(DictionaryEntryEntity::isDeleted)
.toList();
assertEquals(2, deleted.size());
// recreation
@ -1265,7 +1271,10 @@ public class DictionaryTest extends AbstractPersistenceServerServiceTest {
dictionaryClient.addEntry(type2.getType(), type2.getDossierTemplateId(), templateEntries, false, null, DictionaryEntryType.ENTRY);
deleted = entryRepository.findAll().stream().filter(DictionaryEntryEntity::isDeleted).toList();
deleted = entryRepository.findAll()
.stream()
.filter(DictionaryEntryEntity::isDeleted)
.toList();
assertEquals(0, deleted.size());
deletedType1Entities = typeRepository.findAllTypesByDossierTemplateIdOrDossierId(dossierTemplate.getId(), dossier.getId())
@ -1292,6 +1301,72 @@ public class DictionaryTest extends AbstractPersistenceServerServiceTest {
}
@Test
public void testChangeFlagsSuccessful() {
var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();
var dossier1 = dossierTesterAndProvider.provideTestDossier(dossierTemplate, "Dossier1");
var type1 = dictionaryClient.addType(CreateTypeValue.builder()
.type("test_change_flags_true")
.label("Test Change Flags True")
.hexColor("#123456")
.rank(100)
.hint(false)
.hasDictionary(true)
.caseInsensitive(false)
.recommendation(false)
.addToDictionaryAction(false)
.dossierTemplateId(dossierTemplate.getId())
.dossierDictionaryOnly(true)
.build());
dictionaryClient.getAllTypes(dossierTemplate.getId(), dossier1.getId(), false);
dictionaryClient.changeFlags(type1.getType(), dossierTemplate.getId(), dossier1.getId(), true);
String compositeTypeId1 = type1.getType() + ":" + dossierTemplate.getId() + ":" + dossier1.getId();
var updatedTypeEntity1 = typeRepository.findById(compositeTypeId1)
.orElseThrow(() -> new AssertionError("Type entity not found in repository"));
assertThat(updatedTypeEntity1.isAddToDictionaryAction()).isTrue();
}
@Test
public void testChangeFlagsUnsuccessful() {
var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();
var dossier2 = dossierTesterAndProvider.provideTestDossier(dossierTemplate, "Dossier2");
var type2 = dictionaryClient.addType(CreateTypeValue.builder()
.type("test_change_flags_false")
.label("Test Change Flags False")
.hexColor("#654321")
.rank(101)
.hint(false)
.hasDictionary(true)
.caseInsensitive(false)
.recommendation(false)
.addToDictionaryAction(false)
.dossierTemplateId(dossierTemplate.getId())
.dossierDictionaryOnly(false)
.build());
dictionaryClient.getAllTypes(dossierTemplate.getId(), dossier2.getId(), false);
assertThatThrownBy(() -> dictionaryClient.changeFlags(type2.getType(), dossierTemplate.getId(), dossier2.getId(), true))
.isInstanceOf(FeignException.BadRequest.class)
.hasMessageContaining("The addToDictionaryAction flag can only be adjusted for dossierDictionaryOnly-types.");
String compositeTypeId2 = type2.getType() + ":" + dossierTemplate.getId() + ":" + dossier2.getId();
var typeEntity2 = typeRepository.findById(compositeTypeId2)
.orElseThrow(() -> new AssertionError("Type entity not found in repository"));
assertThat(typeEntity2.isAddToDictionaryAction()).isFalse();
}
private static final class ListContentWithoutOrderAndWithoutDuplicatesComparator<T> implements Comparator<List<? extends T>> {
@SuppressWarnings("SuspiciousMethodCalls")

View File

@ -51,15 +51,24 @@ public class DossierAttributeTest extends AbstractPersistenceServerServiceTest {
attribute.setEditable(true);
attribute.setType(DossierAttributeType.TEXT);
dossierAttributeConfigClient.addOrUpdateDossierAttributeConfig(dossier.getDossierTemplateId(), attribute);
var created = dossierAttributeConfigClient.addOrUpdateDossierAttributeConfig(dossier.getDossierTemplateId(), attribute);
assertThat(created.getPlaceholder()).isEqualTo("{{dossier.attribute.Test}}");
loadedAttributes = dossierAttributeConfigClient.getDossierAttributesConfig(dossier.getDossierTemplateId());
assertThat(loadedAttributes.getDossierAttributeConfigs()).isNotEmpty();
assertThat(loadedAttributes.getDossierAttributeConfigs().get(0).getDossierTemplateId()).isEqualTo(dossier.getDossierTemplateId());
attribute.setId(created.getId());
attribute.setLabel("updated test");
var updated = dossierAttributeConfigClient.addOrUpdateDossierAttributeConfig(dossier.getDossierTemplateId(), attribute);
assertThat(updated.getLabel()).isEqualTo("updated test");
assertThat(updated.getPlaceholder()).isEqualTo("{{dossier.attribute.UpdatedTest}}");
attribute.setPlaceholder("{{dossier.attribute.MyOwnPlaceholder}}");
updated = dossierAttributeConfigClient.addOrUpdateDossierAttributeConfig(dossier.getDossierTemplateId(), attribute);
assertThat(updated.getLabel()).isEqualTo("updated test");
assertThat(updated.getPlaceholder()).isEqualTo("{{dossier.attribute.MyOwnPlaceholder}}");
dossierAttributeConfigClient.setDossierAttributesConfig(dossier.getDossierTemplateId(), new DossierAttributesConfig());
loadedAttributes = dossierAttributeConfigClient.getDossierAttributesConfig(dossier.getDossierTemplateId());
assertThat(loadedAttributes.getDossierAttributeConfigs()).isEmpty();

View File

@ -88,9 +88,10 @@ public class FileAttributeTest extends AbstractPersistenceServerServiceTest {
assertThat(loadedConfig.getEncoding()).isEqualTo(ASCII_ENCODING);
List<FileAttributeConfig> configs = new ArrayList<>();
String myOwnPlaceholder = "{{file.attribute.MyOwnPlaceholder}}";
configs.add(FileAttributeConfig.builder().csvColumnHeader("Name").primaryAttribute(true).label("Name").build());
configs.add(FileAttributeConfig.builder().csvColumnHeader("Attribute A").primaryAttribute(true).label("Attribute A").build());
FileAttributeConfig attributeB = FileAttributeConfig.builder().csvColumnHeader("Attribute B").primaryAttribute(true).label("Attribute B").includeInCsvExport(true).build();
FileAttributeConfig attributeB = FileAttributeConfig.builder().csvColumnHeader("Attribute B").primaryAttribute(true).label("Attribute B").placeholder(myOwnPlaceholder).includeInCsvExport(true).build();
configs.add(attributeB);
configs.add(FileAttributeConfig.builder().csvColumnHeader("Attribute C").primaryAttribute(false).label("Attribute C").build());
configs.add(FileAttributeConfig.builder().csvColumnHeader("Attribute D").primaryAttribute(false).label("Attribute D").build());
@ -104,6 +105,7 @@ public class FileAttributeTest extends AbstractPersistenceServerServiceTest {
.findAny()
.get();
assertThat(primaryAttribute.getLabel()).isEqualTo(attributeB.getLabel());
assertThat(primaryAttribute.getPlaceholder()).isEqualTo(attributeB.getPlaceholder());
assertTrue(primaryAttribute.isIncludeInCsvExport());
fileAttributeConfigClient.deleteFileAttribute(dossier.getDossierTemplateId(),
@ -123,6 +125,7 @@ public class FileAttributeTest extends AbstractPersistenceServerServiceTest {
loadedConfigs = fileAttributeConfigClient.getFileAttributesConfiguration(dossier.getDossierTemplateId()).getFileAttributeConfigs();
assertThat(loadedConfigs.size()).isEqualTo(3);
assertThat(loadedConfigs.get(0).getDossierTemplateId()).isEqualTo(dossier.getDossierTemplateId());
FileAttributeConfig newConfig = new FileAttributeConfig();
newConfig.setPrimaryAttribute(true);
@ -130,6 +133,8 @@ public class FileAttributeTest extends AbstractPersistenceServerServiceTest {
var created = fileAttributeConfigClient.addOrUpdateFileAttribute(dossier.getDossierTemplateId(), newConfig);
loadedConfigs = fileAttributeConfigClient.getFileAttributesConfiguration(dossier.getDossierTemplateId()).getFileAttributeConfigs();
assertThat(loadedConfigs.size()).isEqualTo(4);
assertThat(created.getPlaceholder()).isEqualTo("{{file.attribute.TestAttribute}}");
assertThat(created.getCsvColumnHeader()).isNull();
newConfig.setId(created.getId());
newConfig.setLabel("Test Attribute Update");
@ -141,6 +146,14 @@ public class FileAttributeTest extends AbstractPersistenceServerServiceTest {
assertTrue(updated.isIncludeInCsvExport());
assertThat(updated.getPlaceholder()).isEqualTo("{{file.attribute.TestAttributeUpdate}}");
newConfig.setPlaceholder(myOwnPlaceholder);
var e = assertThrows(FeignException.class,
() -> fileAttributeConfigClient.addOrUpdateFileAttribute(dossier.getDossierTemplateId(), newConfig));
assertEquals(409, e.status());
newConfig.setPlaceholder("{{file.attribute.TestAttributeUpdate2}}");
updated = fileAttributeConfigClient.addOrUpdateFileAttribute(dossier.getDossierTemplateId(), newConfig);
assertThat(updated.getPlaceholder()).isEqualTo("{{file.attribute.TestAttributeUpdate2}}");
assertThat(fileClient.getFileStatus(dossier.getId(), file.getId()).getLastFileAttributeChange()).isNull();
fileAttributeClient.setFileAttributes(dossier.getId(), file.getId(), new FileAttributes(Map.of(updated.getId(), "Lorem Ipsum")));