blueprint description template multiplicity changes

This commit is contained in:
amentis 2024-07-09 15:02:16 +03:00
parent b4ae1da886
commit f1ef35ed40
18 changed files with 91 additions and 13 deletions

View File

@ -378,4 +378,14 @@ public class ErrorThesaurusProperties {
public void setRequestHasExpired(ErrorDescription requestHasExpired) {
this.requestHasExpired = requestHasExpired;
}
private ErrorDescription maxDescriptionsExceeded;
public ErrorDescription getMaxDescriptionsExceeded() {
return maxDescriptionsExceeded;
}
public void setMaxDescriptionsExceeded(ErrorDescription maxDescriptionsExceeded) {
this.maxDescriptionsExceeded = maxDescriptionsExceeded;
}
}

View File

@ -222,6 +222,7 @@ public class DescriptionPersist {
.must(() -> !this.isNull(item.getProperties()))
.failOn(DescriptionPersist._properties).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{DescriptionPersist._properties}, LocaleContextHolder.getLocale())),
this.spec()
.iff(() -> item.getStatus() == DescriptionStatus.Finalized)
.must(() -> this.isDescriptionTemplateMaxMultiplicityValid(finalPlanBlueprintEntity, item.getPlanId(), item.getPlanDescriptionTemplateId(), this.isValidGuid(item.getId())))
.failOn(DescriptionPersist._descriptionTemplateId).failWith(this.messageSource.getMessage("Validation.InvalidDescriptionTemplateMultiplicity", new Object[]{DescriptionPersist._descriptionTemplateId}, LocaleContextHolder.getLocale())),
this.refSpec()

View File

@ -39,6 +39,7 @@ import org.opencdmp.commons.types.descriptiontemplate.importexport.fielddata.Ref
import org.opencdmp.commons.types.notification.DataType;
import org.opencdmp.commons.types.notification.FieldInfo;
import org.opencdmp.commons.types.notification.NotificationFieldData;
import org.opencdmp.commons.types.planblueprint.SectionEntity;
import org.opencdmp.commons.types.reference.DefinitionEntity;
import org.opencdmp.convention.ConventionService;
import org.opencdmp.data.*;
@ -221,6 +222,14 @@ public class DescriptionServiceImpl implements DescriptionService {
if (!data.getPlanId().equals(model.getPlanId())) throw new MyValidationException(this.errors.getPlanCanNotChange().getCode(), this.errors.getPlanCanNotChange().getMessage());
if (!data.getPlanDescriptionTemplateId().equals(model.getPlanDescriptionTemplateId())) throw new MyValidationException(this.errors.getPlanDescriptionTemplateCanNotChange().getCode(), this.errors.getPlanDescriptionTemplateCanNotChange().getMessage());
} else {
PlanEntity planEntity = this.entityManager.find(PlanEntity.class, model.getPlanId(), true);
if (planEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{model.getPlanId(), Plan.class.getSimpleName()}, LocaleContextHolder.getLocale()));
PlanBlueprintEntity planBlueprintEntity = this.entityManager.find(PlanBlueprintEntity.class, planEntity.getBlueprintId());
if (planBlueprintEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{planEntity.getBlueprintId(), PlanBlueprint.class.getSimpleName()}, LocaleContextHolder.getLocale()));
if (!this.isDescriptionTemplateMaxMultiplicityValid(planBlueprintEntity, model.getPlanId(),model.getPlanDescriptionTemplateId(), false)) throw new MyValidationException(this.errors.getMaxDescriptionsExceeded().getCode(), this.errors.getMaxDescriptionsExceeded().getMessage());
data = new DescriptionEntity();
data.setId(UUID.randomUUID());
data.setIsActive(IsActive.Active);
@ -275,6 +284,37 @@ public class DescriptionServiceImpl implements DescriptionService {
this.elasticService.persistDescription(data);
return this.builderFactory.builder(DescriptionBuilder.class).authorize(AuthorizationFlags.AllExceptPublic).build(BaseFieldSet.build(fields, Description._id), data);
}
private boolean isDescriptionTemplateMaxMultiplicityValid(PlanBlueprintEntity planBlueprintEntity, UUID planId, UUID planDescriptionTemplateId, Boolean isUpdate){
org.opencdmp.commons.types.planblueprint.DefinitionEntity definition = this.xmlHandlingService.fromXmlSafe(org.opencdmp.commons.types.planblueprint.DefinitionEntity.class, planBlueprintEntity.getDefinition());
if (definition == null || this.conventionService.isListNullOrEmpty(definition.getSections())) return true;
PlanDescriptionTemplateEntity planDescriptionTemplateEntity = this.queryFactory.query(PlanDescriptionTemplateQuery.class).disableTracking().ids(planDescriptionTemplateId).isActive(IsActive.Active).planIds(planId).first();
if (planDescriptionTemplateEntity == null) return true;
List<DescriptionEntity> descriptionEntities = this.queryFactory.query(DescriptionQuery.class).disableTracking().authorize(AuthorizationFlags.AllExceptPublic).planIds(planId).planDescriptionTemplateIds(planDescriptionTemplateId).isActive(IsActive.Active).collect();
for (SectionEntity section: definition.getSections()) {
if (planDescriptionTemplateEntity.getSectionId().equals(section.getId()) && section.getHasTemplates() && !this.conventionService.isListNullOrEmpty(section.getDescriptionTemplates())){
int descriptionsCount;
if (isUpdate) descriptionsCount = -1;
else descriptionsCount = 0;
for (org.opencdmp.commons.types.planblueprint.DescriptionTemplateEntity sectionDescriptionTemplate: section.getDescriptionTemplates()) {
if (sectionDescriptionTemplate.getDescriptionTemplateGroupId().equals(planDescriptionTemplateEntity.getDescriptionTemplateGroupId())){
for (DescriptionEntity description: descriptionEntities){
if (description.getPlanDescriptionTemplateId().equals(planDescriptionTemplateEntity.getId())) descriptionsCount++;
}
if (sectionDescriptionTemplate.getMaxMultiplicity() != null && sectionDescriptionTemplate.getMaxMultiplicity() <= descriptionsCount) return false;
}
}
}
}
return true;
}
@Override
public void updateDescriptionTemplate(UpdateDescriptionTemplatePersist model) throws InvalidApplicationException, IOException {
logger.debug(new MapLogEntry("update description template").And("model", model));
@ -950,12 +990,14 @@ public class DescriptionServiceImpl implements DescriptionService {
DescriptionTemplateEntity descriptionTemplateEntity = this.entityManager.find(DescriptionTemplateEntity.class, data.getDescriptionTemplateId(), true);
if (descriptionTemplateEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{data.getDescriptionTemplateId(), DescriptionTemplate.class.getSimpleName()}, LocaleContextHolder.getLocale()));
persist.setId(data.getId());
persist.setLabel(data.getLabel());
persist.setStatus(DescriptionStatus.Finalized);
persist.setDescription(data.getDescription());
persist.setDescriptionTemplateId(data.getDescriptionTemplateId());
persist.setPlanId(data.getPlanId());
persist.setPlanDescriptionTemplateId(data.getPlanDescriptionTemplateId());
persist.setHash(this.conventionService.hashValue(data.getUpdatedAt()));
org.opencdmp.commons.types.descriptiontemplate.DefinitionEntity definition = this.xmlHandlingService.fromXmlSafe(org.opencdmp.commons.types.descriptiontemplate.DefinitionEntity.class, descriptionTemplateEntity.getDefinition());

View File

@ -119,3 +119,6 @@ error-thesaurus:
requestHasExpired:
code: 143
message: Request has expired
maxDescriptionsExceeded:
code: 144
message: Max descriptions exceeded for this plan

View File

@ -41,6 +41,7 @@ export enum ResponseErrorCode {
PrefillingSourceCodeExists = 141,
InviteUserAlreadyConfirmed = 142,
RequestHasExpired = 143,
MaxDescriptionsExceeded = 144,
// Notification & Annotation Errors
InvalidApiKey = 200,
@ -153,6 +154,8 @@ export class ResponseErrorCodeHelper {
return language.instant("GENERAL.BACKEND-ERRORS.INVITE-USER-ALREADY-CONFIRMED");
case ResponseErrorCode.RequestHasExpired:
return language.instant("GENERAL.BACKEND-ERRORS.REQUEST-HAS-EXPIRED");
case ResponseErrorCode.MaxDescriptionsExceeded:
return language.instant("GENERAL.BACKEND-ERRORS.MAX-DESCRIPTION-EXCEEDED");
default:
return language.instant("GENERAL.SNACK-BAR.NOT-FOUND");
}

View File

@ -261,7 +261,7 @@ export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorMode
if (sectionDescriptionTemplate.maxMultiplicity != null) {
const commonDescriptions = descriptions.filter(x => x.planDescriptionTemplate.descriptionTemplateGroupId == sectionDescriptionTemplate.descriptionTemplateGroupId);
if (commonDescriptions && commonDescriptions.length >= sectionDescriptionTemplate.maxMultiplicity) {
if (commonDescriptions && commonDescriptions.length > sectionDescriptionTemplate.maxMultiplicity) {
rejectedPlanDescriptionTemplates.push.apply(rejectedPlanDescriptionTemplates, commonDescriptions.map(x => x.planDescriptionTemplate));
}
}

View File

@ -674,16 +674,24 @@ export class PlanEditorComponent extends BaseEditor<PlanEditorModel, Plan> imple
}
let multiplicityValidResults: boolean[] = [];
const descriptionTemplatesGroupIds = this.formGroup.get('descriptionTemplates').get(section.id.toString()).value as Guid[] || [];
let descriptionTemplatesGroupIdsWithMaxMultitplicity: Guid[] = [];
section.descriptionTemplates.forEach(sectionDescriptionTemplate => {
if (sectionDescriptionTemplate.maxMultiplicity != null) {
const count = descriptions.filter(x => x.planDescriptionTemplate.descriptionTemplateGroupId == sectionDescriptionTemplate.descriptionTemplateGroupId).length || 0;
if (count >= sectionDescriptionTemplate.maxMultiplicity) multiplicityValidResults.push(false);
else multiplicityValidResults.push(true);
descriptionTemplatesGroupIdsWithMaxMultitplicity.push(sectionDescriptionTemplate.descriptionTemplateGroupId);
} else {
multiplicityValidResults.push(true);
}
})
if (descriptionTemplatesGroupIdsWithMaxMultitplicity.length > 0 && descriptionTemplatesGroupIds.length > 0){
const descriptionTemplatesWithoutMaxMultiplicity = descriptionTemplatesGroupIds.filter(x => !descriptionTemplatesGroupIdsWithMaxMultitplicity.map(y => y).includes(x)) || [];
if (descriptionTemplatesWithoutMaxMultiplicity.length > 0 && this.formGroup.pristine) return true;
}
if (multiplicityValidResults.includes(true)) return true
else return false;
} else {

View File

@ -78,7 +78,8 @@
"PREFILLING-SOURCE-CODE-EXISTS": "The prefilling source code you provided already exists. Please choose a different code.",
"DUPLICATE-PLAN-USER": "You can't invite authors with same role and plan section more than once",
"INVITE-USER-ALREADY-CONFIRMED": "Ιnvitation has already confirmed",
"REQUEST-HAS-EXPIRED": "Request has expired"
"REQUEST-HAS-EXPIRED": "Request has expired",
"MAX-DESCRIPTION-EXCEEDED": "This plan has reached the maximun descriptions for this description template"
},
"FORM-VALIDATION-DISPLAY-DIALOG": {
"WARNING": "Kontuz!",

View File

@ -78,7 +78,8 @@
"PREFILLING-SOURCE-CODE-EXISTS": "The prefilling source code you provided already exists. Please choose a different code.",
"DUPLICATE-PLAN-USER": "You can't invite authors with same role and plan section more than once",
"INVITE-USER-ALREADY-CONFIRMED": "Ιnvitation has already confirmed",
"REQUEST-HAS-EXPIRED": "Request has expired"
"REQUEST-HAS-EXPIRED": "Request has expired",
"MAX-DESCRIPTION-EXCEEDED": "This plan has reached the maximun descriptions for this description template"
},
"FORM-VALIDATION-DISPLAY-DIALOG": {
"WARNING": "Warnung!",

View File

@ -78,7 +78,8 @@
"PREFILLING-SOURCE-CODE-EXISTS": "The prefilling source code you provided already exists. Please choose a different code.",
"DUPLICATE-PLAN-USER": "You can't invite authors with same role and plan section more than once",
"INVITE-USER-ALREADY-CONFIRMED": "Ιnvitation has already confirmed",
"REQUEST-HAS-EXPIRED": "Request has expired"
"REQUEST-HAS-EXPIRED": "Request has expired",
"MAX-DESCRIPTION-EXCEEDED": "This plan has reached the maximun descriptions for this description template"
},
"FORM-VALIDATION-DISPLAY-DIALOG": {
"WARNING": "Warning!",

View File

@ -78,7 +78,8 @@
"PREFILLING-SOURCE-CODE-EXISTS": "The prefilling source code you provided already exists. Please choose a different code.",
"DUPLICATE-PLAN-USER": "You can't invite authors with same role and plan section more than once",
"INVITE-USER-ALREADY-CONFIRMED": "Ιnvitation has already confirmed",
"REQUEST-HAS-EXPIRED": "Request has expired"
"REQUEST-HAS-EXPIRED": "Request has expired",
"MAX-DESCRIPTION-EXCEEDED": "This plan has reached the maximun descriptions for this description template"
},
"FORM-VALIDATION-DISPLAY-DIALOG": {
"WARNING": "Atención!",

View File

@ -78,7 +78,8 @@
"PREFILLING-SOURCE-CODE-EXISTS": "The prefilling source code you provided already exists. Please choose a different code.",
"DUPLICATE-PLAN-USER": "You can't invite authors with same role and plan section more than once",
"INVITE-USER-ALREADY-CONFIRMED": "Ιnvitation has already confirmed",
"REQUEST-HAS-EXPIRED": "Request has expired"
"REQUEST-HAS-EXPIRED": "Request has expired",
"MAX-DESCRIPTION-EXCEEDED": "This plan has reached the maximun descriptions for this description template"
},
"FORM-VALIDATION-DISPLAY-DIALOG": {
"WARNING": "Προσοχή!",

View File

@ -78,7 +78,8 @@
"PREFILLING-SOURCE-CODE-EXISTS": "The prefilling source code you provided already exists. Please choose a different code.",
"DUPLICATE-PLAN-USER": "You can't invite authors with same role and plan section more than once",
"INVITE-USER-ALREADY-CONFIRMED": "Ιnvitation has already confirmed",
"REQUEST-HAS-EXPIRED": "Request has expired"
"REQUEST-HAS-EXPIRED": "Request has expired",
"MAX-DESCRIPTION-EXCEEDED": "This plan has reached the maximun descriptions for this description template"
},
"FORM-VALIDATION-DISPLAY-DIALOG": {
"WARNING": "Oprez!",

View File

@ -78,7 +78,8 @@
"PREFILLING-SOURCE-CODE-EXISTS": "The prefilling source code you provided already exists. Please choose a different code.",
"DUPLICATE-PLAN-USER": "You can't invite authors with same role and plan section more than once",
"INVITE-USER-ALREADY-CONFIRMED": "Ιnvitation has already confirmed",
"REQUEST-HAS-EXPIRED": "Request has expired"
"REQUEST-HAS-EXPIRED": "Request has expired",
"MAX-DESCRIPTION-EXCEEDED": "This plan has reached the maximun descriptions for this description template"
},
"FORM-VALIDATION-DISPLAY-DIALOG": {
"WARNING": "Ostrzeżenie!",

View File

@ -78,7 +78,8 @@
"PREFILLING-SOURCE-CODE-EXISTS": "The prefilling source code you provided already exists. Please choose a different code.",
"DUPLICATE-PLAN-USER": "You can't invite authors with same role and plan section more than once",
"INVITE-USER-ALREADY-CONFIRMED": "Ιnvitation has already confirmed",
"REQUEST-HAS-EXPIRED": "Request has expired"
"REQUEST-HAS-EXPIRED": "Request has expired",
"MAX-DESCRIPTION-EXCEEDED": "This plan has reached the maximun descriptions for this description template"
},
"FORM-VALIDATION-DISPLAY-DIALOG": {
"WARNING": "Atenção!",

View File

@ -78,7 +78,8 @@
"PREFILLING-SOURCE-CODE-EXISTS": "The prefilling source code you provided already exists. Please choose a different code.",
"DUPLICATE-PLAN-USER": "You can't invite authors with same role and plan section more than once",
"INVITE-USER-ALREADY-CONFIRMED": "Ιnvitation has already confirmed",
"REQUEST-HAS-EXPIRED": "Request has expired"
"REQUEST-HAS-EXPIRED": "Request has expired",
"MAX-DESCRIPTION-EXCEEDED": "This plan has reached the maximun descriptions for this description template"
},
"FORM-VALIDATION-DISPLAY-DIALOG": {
"WARNING": "Upozornenie!",

View File

@ -78,7 +78,8 @@
"PREFILLING-SOURCE-CODE-EXISTS": "The prefilling source code you provided already exists. Please choose a different code.",
"DUPLICATE-PLAN-USER": "You can't invite authors with same role and plan section more than once",
"INVITE-USER-ALREADY-CONFIRMED": "Ιnvitation has already confirmed",
"REQUEST-HAS-EXPIRED": "Request has expired"
"REQUEST-HAS-EXPIRED": "Request has expired",
"MAX-DESCRIPTION-EXCEEDED": "This plan has reached the maximun descriptions for this description template"
},
"FORM-VALIDATION-DISPLAY-DIALOG": {
"WARNING": "Oprez!",

View File

@ -78,7 +78,8 @@
"PREFILLING-SOURCE-CODE-EXISTS": "The prefilling source code you provided already exists. Please choose a different code.",
"DUPLICATE-PLAN-USER": "You can't invite authors with same role and plan section more than once",
"INVITE-USER-ALREADY-CONFIRMED": "Ιnvitation has already confirmed",
"REQUEST-HAS-EXPIRED": "Request has expired"
"REQUEST-HAS-EXPIRED": "Request has expired",
"MAX-DESCRIPTION-EXCEEDED": "This plan has reached the maximun descriptions for this description template"
},
"FORM-VALIDATION-DISPLAY-DIALOG": {
"WARNING": "Uyarı!",