implement blueprint code

This commit is contained in:
CITE\amentis 2024-07-29 17:11:11 +03:00
parent cdb19efaa6
commit dc3e26e581
23 changed files with 198 additions and 28 deletions

View File

@ -17,6 +17,9 @@ public class BlueprintImportExport {
@XmlElement(name = "label") @XmlElement(name = "label")
private String label; private String label;
@XmlElement(name = "code")
private String code;
@XmlElement(name = "definition") @XmlElement(name = "definition")
private BlueprintDefinitionImportExport planBlueprintDefinition; private BlueprintDefinitionImportExport planBlueprintDefinition;
@ -39,6 +42,14 @@ public class BlueprintImportExport {
this.label = label; this.label = label;
} }
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public BlueprintDefinitionImportExport getPlanBlueprintDefinition() { public BlueprintDefinitionImportExport getPlanBlueprintDefinition() {
return this.planBlueprintDefinition; return this.planBlueprintDefinition;
} }

View File

@ -31,6 +31,11 @@ public class PlanBlueprintEntity extends TenantScopedBaseEntity {
public static final int _labelLength = 250; public static final int _labelLength = 250;
@Column(name = "code", length = _codeLength, nullable = false)
private String code;
public final static String _code = "code";
public final static int _codeLength = 200;
@Type(SQLXMLType.class) @Type(SQLXMLType.class)
@Column(name = "definition", columnDefinition = "xml") @Column(name = "definition", columnDefinition = "xml")
private String definition; private String definition;
@ -91,6 +96,14 @@ public class PlanBlueprintEntity extends TenantScopedBaseEntity {
this.label = label; this.label = label;
} }
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getDefinition() { public String getDefinition() {
return this.definition; return this.definition;
} }

View File

@ -458,4 +458,24 @@ public class ErrorThesaurusProperties {
public void setDescriptionTemplateImportNotFound(ErrorDescription descriptionTemplateImportNotFound) { public void setDescriptionTemplateImportNotFound(ErrorDescription descriptionTemplateImportNotFound) {
this.descriptionTemplateImportNotFound = descriptionTemplateImportNotFound; this.descriptionTemplateImportNotFound = descriptionTemplateImportNotFound;
} }
private ErrorDescription planBlueprintCodeExists;
public ErrorDescription getPlanBlueprintCodeExists() {
return planBlueprintCodeExists;
}
public void setPlanBlueprintCodeExists(ErrorDescription planBlueprintCodeExists) {
this.planBlueprintCodeExists = planBlueprintCodeExists;
}
private ErrorDescription planBlueprintImportNotFound;
public ErrorDescription getPlanBlueprintImportNotFound() {
return planBlueprintImportNotFound;
}
public void setPlanBlueprintImportNotFound(ErrorDescription planBlueprintImportNotFound) {
this.planBlueprintImportNotFound = planBlueprintImportNotFound;
}
} }

View File

@ -62,6 +62,8 @@ public class PlanBlueprintBuilder extends BaseBuilder<PlanBlueprint, PlanBluepri
m.setId(d.getId()); m.setId(d.getId());
if (fields.hasField(this.asIndexer(PlanBlueprint._label))) if (fields.hasField(this.asIndexer(PlanBlueprint._label)))
m.setLabel(d.getLabel()); m.setLabel(d.getLabel());
if (fields.hasField(this.asIndexer(PlanBlueprint._code)))
m.setCode(d.getCode());
if (fields.hasField(this.asIndexer(PlanBlueprint._status))) if (fields.hasField(this.asIndexer(PlanBlueprint._status)))
m.setStatus(d.getStatus()); m.setStatus(d.getStatus());
if (fields.hasField(this.asIndexer(PlanBlueprint._groupId))) if (fields.hasField(this.asIndexer(PlanBlueprint._groupId)))

View File

@ -30,6 +30,10 @@ public class PlanBlueprintPersist {
public static final String _label = "label"; public static final String _label = "label";
private String code;
public final static String _code = "code";
private DefinitionPersist definition; private DefinitionPersist definition;
public static final String _definition = "definition"; public static final String _definition = "definition";
@ -58,6 +62,14 @@ public class PlanBlueprintPersist {
this.label = label; this.label = label;
} }
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public DefinitionPersist getDefinition() { public DefinitionPersist getDefinition() {
return this.definition; return this.definition;
} }
@ -124,7 +136,13 @@ public class PlanBlueprintPersist {
this.spec() this.spec()
.must(() -> !this.isNull(item.getStatus())) .must(() -> !this.isNull(item.getStatus()))
.failOn(PlanBlueprintPersist._status).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{PlanBlueprintPersist._status}, LocaleContextHolder.getLocale())), .failOn(PlanBlueprintPersist._status).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{PlanBlueprintPersist._status}, LocaleContextHolder.getLocale())),
this.spec()
.must(() -> !this.isEmpty(item.getCode()))
.failOn(PlanBlueprintPersist._code).failWith(messageSource.getMessage("Validation_Required", new Object[]{PlanBlueprintPersist._code}, LocaleContextHolder.getLocale())),
this.spec()
.iff(() -> !this.isEmpty(item.getCode()))
.must(() -> this.lessEqualLength(item.getCode(), PlanBlueprintEntity._codeLength))
.failOn(PlanBlueprintPersist._code).failWith(messageSource.getMessage("Validation_MaxLength", new Object[]{PlanBlueprintPersist._code}, LocaleContextHolder.getLocale())),
this.spec() this.spec()
.iff(() -> item.getStatus() == PlanBlueprintStatus.Finalized) .iff(() -> item.getStatus() == PlanBlueprintStatus.Finalized)
.must(() -> !this.isNull(item.getDefinition())) .must(() -> !this.isNull(item.getDefinition()))

View File

@ -17,6 +17,11 @@ public class PlanBlueprint {
public static final String _label = "label"; public static final String _label = "label";
private String code;
public final static String _code = "code";
private Definition definition; private Definition definition;
public static final String _definition = "definition"; public static final String _definition = "definition";
@ -72,6 +77,14 @@ public class PlanBlueprint {
this.label = label; this.label = label;
} }
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public Definition getDefinition() { public Definition getDefinition() {
return definition; return definition;
} }

View File

@ -41,6 +41,8 @@ public class PlanBlueprintQuery extends QueryBase<PlanBlueprintEntity> {
private Collection<Short> versions; private Collection<Short> versions;
private Collection<String> codes;
private Collection<PlanBlueprintVersionStatus> versionStatuses; private Collection<PlanBlueprintVersionStatus> versionStatuses;
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None); private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
@ -155,6 +157,21 @@ public class PlanBlueprintQuery extends QueryBase<PlanBlueprintEntity> {
return this; return this;
} }
public PlanBlueprintQuery codes(String value) {
this.codes = List.of(value);
return this;
}
public PlanBlueprintQuery codes(String... value) {
this.codes = Arrays.asList(value);
return this;
}
public PlanBlueprintQuery codes(Collection<String> values) {
this.codes = values;
return this;
}
public PlanBlueprintQuery authorize(EnumSet<AuthorizationFlags> values) { public PlanBlueprintQuery authorize(EnumSet<AuthorizationFlags> values) {
this.authorize = values; this.authorize = values;
return this; return this;
@ -213,7 +230,9 @@ public class PlanBlueprintQuery extends QueryBase<PlanBlueprintEntity> {
} }
if (this.like != null && !this.like.isBlank()) { if (this.like != null && !this.like.isBlank()) {
predicates.add(this.queryUtilsService.ilike(queryContext.CriteriaBuilder, queryContext.Root.get(PlanBlueprintEntity._label), this.like)); predicates.add(queryContext.CriteriaBuilder.or(this.queryUtilsService.ilike(queryContext.CriteriaBuilder, queryContext.Root.get(PlanBlueprintEntity._label), this.like),
this.queryUtilsService.ilike(queryContext.CriteriaBuilder, queryContext.Root.get(PlanBlueprintEntity._code), this.like)
));
} }
if (this.isActives != null) { if (this.isActives != null) {
@ -251,6 +270,13 @@ public class PlanBlueprintQuery extends QueryBase<PlanBlueprintEntity> {
predicates.add(inClause); predicates.add(inClause);
} }
if (this.codes != null) {
CriteriaBuilder.In<String> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(PlanBlueprintEntity._code));
for (String item : this.codes)
inClause.value(item);
predicates.add(inClause);
}
if (!predicates.isEmpty()) { if (!predicates.isEmpty()) {
Predicate[] predicatesArray = predicates.toArray(new Predicate[0]); Predicate[] predicatesArray = predicates.toArray(new Predicate[0]);
return queryContext.CriteriaBuilder.and(predicatesArray); return queryContext.CriteriaBuilder.and(predicatesArray);
@ -265,6 +291,7 @@ public class PlanBlueprintQuery extends QueryBase<PlanBlueprintEntity> {
item.setId(QueryBase.convertSafe(tuple, columns, PlanBlueprintEntity._id, UUID.class)); item.setId(QueryBase.convertSafe(tuple, columns, PlanBlueprintEntity._id, UUID.class));
item.setTenantId(QueryBase.convertSafe(tuple, columns, PlanBlueprintEntity._tenantId, UUID.class)); item.setTenantId(QueryBase.convertSafe(tuple, columns, PlanBlueprintEntity._tenantId, UUID.class));
item.setLabel(QueryBase.convertSafe(tuple, columns, PlanBlueprintEntity._label, String.class)); item.setLabel(QueryBase.convertSafe(tuple, columns, PlanBlueprintEntity._label, String.class));
item.setCode(QueryBase.convertSafe(tuple, columns, PlanBlueprintEntity._code, String.class));
item.setDefinition(QueryBase.convertSafe(tuple, columns, PlanBlueprintEntity._definition, String.class)); item.setDefinition(QueryBase.convertSafe(tuple, columns, PlanBlueprintEntity._definition, String.class));
item.setStatus(QueryBase.convertSafe(tuple, columns, PlanBlueprintEntity._status, PlanBlueprintStatus.class)); item.setStatus(QueryBase.convertSafe(tuple, columns, PlanBlueprintEntity._status, PlanBlueprintStatus.class));
item.setGroupId(QueryBase.convertSafe(tuple, columns, PlanBlueprintEntity._groupId, UUID.class)); item.setGroupId(QueryBase.convertSafe(tuple, columns, PlanBlueprintEntity._groupId, UUID.class));
@ -282,6 +309,8 @@ public class PlanBlueprintQuery extends QueryBase<PlanBlueprintEntity> {
return PlanBlueprintEntity._id; return PlanBlueprintEntity._id;
else if (item.match(PlanBlueprint._label)) else if (item.match(PlanBlueprint._label))
return PlanBlueprintEntity._label; return PlanBlueprintEntity._label;
else if (item.match(PlanBlueprint._code))
return PlanBlueprintEntity._code;
else if (item.match(PlanBlueprint._definition)) else if (item.match(PlanBlueprint._definition))
return PlanBlueprintEntity._definition; return PlanBlueprintEntity._definition;
else if (item.prefix(PlanBlueprint._definition)) else if (item.prefix(PlanBlueprint._definition))

View File

@ -1367,8 +1367,8 @@ public class DescriptionServiceImpl implements DescriptionService {
if (descriptionXml.getDescriptionTemplate() != null) { if (descriptionXml.getDescriptionTemplate() != null) {
DescriptionTemplateEntity descriptionTemplateEntity = this.queryFactory.query(DescriptionTemplateQuery.class).disableTracking().ids(UUID.randomUUID()).first(); DescriptionTemplateEntity descriptionTemplateEntity = this.queryFactory.query(DescriptionTemplateQuery.class).disableTracking().ids(descriptionXml.getDescriptionTemplate().getId()).first();
if (descriptionTemplateEntity == null) descriptionTemplateEntity = this.queryFactory.query(DescriptionTemplateQuery.class).disableTracking().groupIds(UUID.randomUUID()).versionStatuses(DescriptionTemplateVersionStatus.Current).isActive(IsActive.Active).statuses(DescriptionTemplateStatus.Finalized).first(); if (descriptionTemplateEntity == null) descriptionTemplateEntity = this.queryFactory.query(DescriptionTemplateQuery.class).disableTracking().groupIds(descriptionXml.getDescriptionTemplate().getGroupId()).versionStatuses(DescriptionTemplateVersionStatus.Current).isActive(IsActive.Active).statuses(DescriptionTemplateStatus.Finalized).first();
UUID descriptionTemplateId; UUID descriptionTemplateId;
if (descriptionTemplateEntity != null){ if (descriptionTemplateEntity != null){
descriptionTemplateId = descriptionTemplateEntity.getId(); descriptionTemplateId = descriptionTemplateEntity.getId();

View File

@ -214,12 +214,10 @@ public class DescriptionTemplateServiceImpl implements DescriptionTemplateServic
data.setUpdatedAt(Instant.now()); data.setUpdatedAt(Instant.now());
data.setDefinition(this.xmlHandlingService.toXml(this.buildDefinitionEntity(model.getDefinition()))); data.setDefinition(this.xmlHandlingService.toXml(this.buildDefinitionEntity(model.getDefinition())));
Long descriptionTemplateCodes = 0L;
if (model.getCode() != null) descriptionTemplateCodes = this.queryFactory.query(DescriptionTemplateQuery.class).disableTracking().codes(model.getCode()).count();
if (isUpdate) { if (isUpdate) {
this.entityManager.merge(data); this.entityManager.merge(data);
} else { } else {
Long descriptionTemplateCodes = this.queryFactory.query(DescriptionTemplateQuery.class).disableTracking().codes(model.getCode()).count();
if (descriptionTemplateCodes > 0) throw new MyValidationException(this.errors.getDescriptionTemplateCodeExists().getCode(), this.errors.getDescriptionTemplateCodeExists().getMessage()); if (descriptionTemplateCodes > 0) throw new MyValidationException(this.errors.getDescriptionTemplateCodeExists().getCode(), this.errors.getDescriptionTemplateCodeExists().getMessage());
this.entityManager.persist(data); this.entityManager.persist(data);
this.accountingService.increase(UsageLimitTargetMetric.DESCRIPTION_TEMPLATE_COUNT.getValue()); this.accountingService.increase(UsageLimitTargetMetric.DESCRIPTION_TEMPLATE_COUNT.getValue());

View File

@ -103,6 +103,8 @@ public class DescriptionTemplateTypeServiceImpl implements DescriptionTemplateTy
data = this.entityManager.find(DescriptionTemplateTypeEntity.class, model.getId()); data = this.entityManager.find(DescriptionTemplateTypeEntity.class, model.getId());
if (data == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), DescriptionTemplateType.class.getSimpleName()}, LocaleContextHolder.getLocale())); if (data == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), DescriptionTemplateType.class.getSimpleName()}, LocaleContextHolder.getLocale()));
if (!this.conventionService.hashValue(data.getUpdatedAt()).equals(model.getHash())) throw new MyValidationException(this.errors.getHashConflict().getCode(), this.errors.getHashConflict().getMessage()); if (!this.conventionService.hashValue(data.getUpdatedAt()).equals(model.getHash())) throw new MyValidationException(this.errors.getHashConflict().getCode(), this.errors.getHashConflict().getMessage());
if (!data.getCode().equals(model.getCode()))
throw new MyForbiddenException("Code can not change");
} else { } else {
this.usageLimitService.checkIncrease(UsageLimitTargetMetric.DESCRIPTION_TEMPLATE_TYPE_COUNT); this.usageLimitService.checkIncrease(UsageLimitTargetMetric.DESCRIPTION_TEMPLATE_TYPE_COUNT);
data = new DescriptionTemplateTypeEntity(); data = new DescriptionTemplateTypeEntity();
@ -116,12 +118,10 @@ public class DescriptionTemplateTypeServiceImpl implements DescriptionTemplateTy
data.setStatus(model.getStatus()); data.setStatus(model.getStatus());
data.setUpdatedAt(Instant.now()); data.setUpdatedAt(Instant.now());
Long descriptionTemplateTypeCodes = this.queryFactory.query(DescriptionTemplateTypeQuery.class).disableTracking().codes(model.getCode()).count();
if (isUpdate) { if (isUpdate) {
if (descriptionTemplateTypeCodes > 1) throw new MyValidationException(this.errors.getDescriptionTemplateTypeCodeExists().getCode(), this.errors.getDescriptionTemplateTypeCodeExists().getMessage());
this.entityManager.merge(data); this.entityManager.merge(data);
} else { } else {
Long descriptionTemplateTypeCodes = this.queryFactory.query(DescriptionTemplateTypeQuery.class).disableTracking().codes(model.getCode()).count();
if (descriptionTemplateTypeCodes > 0) throw new MyValidationException(this.errors.getDescriptionTemplateTypeCodeExists().getCode(), this.errors.getDescriptionTemplateTypeCodeExists().getMessage()); if (descriptionTemplateTypeCodes > 0) throw new MyValidationException(this.errors.getDescriptionTemplateTypeCodeExists().getCode(), this.errors.getDescriptionTemplateTypeCodeExists().getMessage());
this.entityManager.persist(data); this.entityManager.persist(data);
this.accountingService.increase(UsageLimitTargetMetric.DESCRIPTION_TEMPLATE_TYPE_COUNT.getValue()); this.accountingService.increase(UsageLimitTargetMetric.DESCRIPTION_TEMPLATE_TYPE_COUNT.getValue());

View File

@ -1912,8 +1912,12 @@ public class PlanServiceImpl implements PlanService {
if (planBlueprintEntity != null){ if (planBlueprintEntity != null){
return planBlueprintEntity.getId(); return planBlueprintEntity.getId();
} else { } else {
PlanBlueprint persisted = this.planBlueprintService.importXml(planXml.getBlueprint(), null, planXml.getBlueprint().getLabel(), new BaseFieldSet().ensure(PlanBlueprint._label).ensure(PlanBlueprint._hash)); planBlueprintEntity = this.queryFactory.query(PlanBlueprintQuery.class).disableTracking().codes(planXml.getBlueprint().getCode()).first();
return persisted.getId(); if (planBlueprintEntity == null) {
throw new MyValidationException(this.errors.getPlanBlueprintImportNotFound().getCode(), planXml.getBlueprint().getCode());
} else {
return planBlueprintEntity.getId();
}
} }
} }
return null; return null;

View File

@ -137,6 +137,8 @@ public class PlanBlueprintServiceImpl implements PlanBlueprintService {
throw new MyValidationException(this.errors.getHashConflict().getCode(), this.errors.getHashConflict().getMessage()); throw new MyValidationException(this.errors.getHashConflict().getCode(), this.errors.getHashConflict().getMessage());
if (data.getStatus().equals(PlanBlueprintStatus.Finalized)) if (data.getStatus().equals(PlanBlueprintStatus.Finalized))
throw new MyForbiddenException("Cannot update finalized blueprint"); throw new MyForbiddenException("Cannot update finalized blueprint");
if (!data.getCode().equals(model.getCode()))
throw new MyForbiddenException("Code can not change");
} else { } else {
this.usageLimitService.checkIncrease(UsageLimitTargetMetric.BLUEPRINT_COUNT); this.usageLimitService.checkIncrease(UsageLimitTargetMetric.BLUEPRINT_COUNT);
data = new PlanBlueprintEntity(); data = new PlanBlueprintEntity();
@ -162,13 +164,16 @@ public class PlanBlueprintServiceImpl implements PlanBlueprintService {
} }
data.setLabel(model.getLabel()); data.setLabel(model.getLabel());
data.setCode(model.getCode());
data.setStatus(model.getStatus()); data.setStatus(model.getStatus());
data.setUpdatedAt(Instant.now()); data.setUpdatedAt(Instant.now());
data.setDefinition(this.xmlHandlingService.toXml(this.buildDefinitionEntity(model.getDefinition()))); data.setDefinition(this.xmlHandlingService.toXml(this.buildDefinitionEntity(model.getDefinition())));
if (isUpdate) if (isUpdate) {
this.entityManager.merge(data); this.entityManager.merge(data);
else{ } else {
Long planBlueprintCodes = this.queryFactory.query(PlanBlueprintQuery.class).disableTracking().codes(model.getCode()).count();
if (planBlueprintCodes > 0) throw new MyValidationException(this.errors.getPlanBlueprintCodeExists().getCode(), this.errors.getPlanBlueprintCodeExists().getMessage());
this.entityManager.persist(data); this.entityManager.persist(data);
this.accountingService.increase(UsageLimitTargetMetric.BLUEPRINT_COUNT.getValue()); this.accountingService.increase(UsageLimitTargetMetric.BLUEPRINT_COUNT.getValue());
} }
@ -465,6 +470,7 @@ public class PlanBlueprintServiceImpl implements PlanBlueprintService {
data.setStatus(PlanBlueprintStatus.Draft); data.setStatus(PlanBlueprintStatus.Draft);
data.setDefinition(this.xmlHandlingService.toXml(this.buildDefinitionEntity(model.getDefinition()))); data.setDefinition(this.xmlHandlingService.toXml(this.buildDefinitionEntity(model.getDefinition())));
data.setGroupId(oldPlanBlueprintEntity.getGroupId()); data.setGroupId(oldPlanBlueprintEntity.getGroupId());
data.setCode(oldPlanBlueprintEntity.getCode());
data.setVersion((short) (oldPlanBlueprintEntity.getVersion() + 1)); data.setVersion((short) (oldPlanBlueprintEntity.getVersion() + 1));
data.setVersionStatus(PlanBlueprintVersionStatus.NotFinalized); data.setVersionStatus(PlanBlueprintVersionStatus.NotFinalized);
data.setCreatedAt(Instant.now()); data.setCreatedAt(Instant.now());
@ -518,6 +524,7 @@ public class PlanBlueprintServiceImpl implements PlanBlueprintService {
BlueprintImportExport xml = new BlueprintImportExport(); BlueprintImportExport xml = new BlueprintImportExport();
xml.setId(entity.getId()); xml.setId(entity.getId());
xml.setLabel(entity.getLabel()); xml.setLabel(entity.getLabel());
xml.setCode(entity.getCode());
xml.setGroupId(entity.getGroupId()); xml.setGroupId(entity.getGroupId());
DefinitionEntity planBlueprintDefinition = this.xmlHandlingService.fromXml(DefinitionEntity.class, entity.getDefinition()); DefinitionEntity planBlueprintDefinition = this.xmlHandlingService.fromXml(DefinitionEntity.class, entity.getDefinition());
xml.setPlanBlueprintDefinition(this.definitionXmlToExport(planBlueprintDefinition)); xml.setPlanBlueprintDefinition(this.definitionXmlToExport(planBlueprintDefinition));
@ -669,23 +676,43 @@ public class PlanBlueprintServiceImpl implements PlanBlueprintService {
.groupIds(groupId) .groupIds(groupId)
.count() : 0; .count() : 0;
if (activeBlueprintForTheGroup == 0 && !this.conventionService.isNullOrEmpty(planBlueprintDefinition.getCode())) {
this.queryFactory.query(PlanBlueprintQuery.class).disableTracking()
.isActive(IsActive.Active)
.codes(planBlueprintDefinition.getCode())
.count();
}
if (activeBlueprintForTheGroup == 0) { if (activeBlueprintForTheGroup == 0) {
PlanBlueprintPersist persist = new PlanBlueprintPersist(); PlanBlueprintPersist persist = new PlanBlueprintPersist();
persist.setLabel(label); persist.setLabel(label);
persist.setCode(planBlueprintDefinition.getCode());
persist.setStatus(PlanBlueprintStatus.Draft); persist.setStatus(PlanBlueprintStatus.Draft);
persist.setDefinition(this.xmlDefinitionToPersist(planBlueprintDefinition.getPlanBlueprintDefinition())); persist.setDefinition(this.xmlDefinitionToPersist(planBlueprintDefinition.getPlanBlueprintDefinition()));
this.validatorFactory.validator(PlanBlueprintPersist.PlanBlueprintPersistValidator.class).validateForce(persist); this.validatorFactory.validator(PlanBlueprintPersist.PlanBlueprintPersistValidator.class).validateForce(persist);
return this.persist(persist, groupId, fields); return this.persist(persist, groupId, fields);
} else { } else {
PlanBlueprintEntity latestVersionPlanBlueprint = this.queryFactory.query(PlanBlueprintQuery.class) PlanBlueprintEntity latestVersionPlanBlueprint = null;
if (groupId != null) {
latestVersionPlanBlueprint = this.queryFactory.query(PlanBlueprintQuery.class)
.disableTracking() .disableTracking()
.versionStatuses(PlanBlueprintVersionStatus.Current) .versionStatuses(PlanBlueprintVersionStatus.Current)
.isActive(IsActive.Active) .isActive(IsActive.Active)
.statuses(PlanBlueprintStatus.Finalized) .statuses(PlanBlueprintStatus.Finalized)
.groupIds(groupId) .groupIds(groupId)
.first(); .first();
}
if (latestVersionPlanBlueprint == null && !this.conventionService.isNullOrEmpty(planBlueprintDefinition.getCode())) {
latestVersionPlanBlueprint = this.queryFactory.query(PlanBlueprintQuery.class)
.disableTracking()
.versionStatuses(PlanBlueprintVersionStatus.Current)
.isActive(IsActive.Active)
.statuses(PlanBlueprintStatus.Finalized)
.codes(planBlueprintDefinition.getCode())
.first();
}
if (latestVersionPlanBlueprint == null) throw new MyValidationException(this.errors.getPlanIsNotFinalized().getCode(), this.errors.getPlanIsNotFinalized().getMessage()); if (latestVersionPlanBlueprint == null) throw new MyValidationException(this.errors.getPlanIsNotFinalized().getCode(), this.errors.getPlanIsNotFinalized().getMessage());
NewVersionPlanBlueprintPersist persist = new NewVersionPlanBlueprintPersist(); NewVersionPlanBlueprintPersist persist = new NewVersionPlanBlueprintPersist();
persist.setId(latestVersionPlanBlueprint.getId()); persist.setId(latestVersionPlanBlueprint.getId());

View File

@ -142,4 +142,10 @@ error-thesaurus:
message: Description template code exists message: Description template code exists
descriptionTemplateImportNotFound: descriptionTemplateImportNotFound:
code: 151 code: 151
message: Description template code exists message: Description template not found
planBlueprintCodeExists:
code: 152
message: Plan blueprint code exists
planBlueprintImportNotFound:
code: 153
message: Plan blueprint code not found

View File

@ -47,6 +47,8 @@ export enum ResponseErrorCode {
referenceTypeImportNotFound = 149, referenceTypeImportNotFound = 149,
descriptionTemplateCodeExists = 150, descriptionTemplateCodeExists = 150,
descriptionTemplateImportNotFound = 151, descriptionTemplateImportNotFound = 151,
planBlueprintCodeExists = 152,
planBlueprintImportNotFound = 153,
// Notification & Annotation Errors // Notification & Annotation Errors
InvalidApiKey = 200, InvalidApiKey = 200,
@ -175,6 +177,8 @@ export class ResponseErrorCodeHelper {
return language.instant("GENERAL.BACKEND-ERRORS.DESCRIPTION-TEMPLATE-CODE-EXISTS"); return language.instant("GENERAL.BACKEND-ERRORS.DESCRIPTION-TEMPLATE-CODE-EXISTS");
case ResponseErrorCode.descriptionTemplateImportNotFound: case ResponseErrorCode.descriptionTemplateImportNotFound:
return language.instant("GENERAL.BACKEND-ERRORS.DESCRIPTION-TEMPLATE-IMPORT-NOT-FOUND"); return language.instant("GENERAL.BACKEND-ERRORS.DESCRIPTION-TEMPLATE-IMPORT-NOT-FOUND");
case ResponseErrorCode.planBlueprintCodeExists:
return language.instant("GENERAL.BACKEND-ERRORS.PLAN-BLUEPRINT-CODE-EXISTS");
default: default:
return language.instant("GENERAL.SNACK-BAR.NOT-FOUND"); return language.instant("GENERAL.SNACK-BAR.NOT-FOUND");
} }

View File

@ -11,6 +11,7 @@ import { PlanBlueprintVersionStatus } from "@app/core/common/enum/plan-blueprint
export interface PlanBlueprint extends BaseEntity { export interface PlanBlueprint extends BaseEntity {
label: string; label: string;
code: string;
definition: PlanBlueprintDefinition; definition: PlanBlueprintDefinition;
status: PlanBlueprintStatus; status: PlanBlueprintStatus;
version: number; version: number;
@ -71,6 +72,7 @@ export interface ReferenceTypeFieldInSection extends FieldInSection {
// //
export interface PlanBlueprintPersist extends BaseEntityPersist { export interface PlanBlueprintPersist extends BaseEntityPersist {
label: string; label: string;
code: string;
definition: PlanBlueprintDefinitionPersist; definition: PlanBlueprintDefinitionPersist;
status: PlanBlueprintStatus; status: PlanBlueprintStatus;
} }

View File

@ -118,7 +118,7 @@ export class DescriptionTemplateTypeEditorComponent extends BaseEditor<Descripti
} }
buildForm() { buildForm() {
this.formGroup = this.editorModel.buildForm(null, this.isDeleted || !this.authService.hasPermission(AppPermission.EditDescriptionTemplateType)); this.formGroup = this.editorModel.buildForm(null, this.isDeleted || !this.authService.hasPermission(AppPermission.EditDescriptionTemplateType), this.isNew);
this.descriptionTemplateTypeEditorService.setValidationErrorModel(this.editorModel.validationErrorModel); this.descriptionTemplateTypeEditorService.setValidationErrorModel(this.editorModel.validationErrorModel);
if (this.isFinalized) { if (this.isFinalized) {

View File

@ -32,13 +32,13 @@ export class DescriptionTemplateTypeEditorModel extends BaseEditorModel implemen
return this; return this;
} }
buildForm(context: ValidationContext = null, disabled: boolean = false): UntypedFormGroup { buildForm(context: ValidationContext = null, disabled: boolean = false, isNew: boolean = false): UntypedFormGroup {
if (context == null) { context = this.createValidationContext(); } if (context == null) { context = this.createValidationContext(); }
return this.formBuilder.group({ return this.formBuilder.group({
id: [{ value: this.id, disabled: disabled }, context.getValidation('id').validators], id: [{ value: this.id, disabled: disabled }, context.getValidation('id').validators],
name: [{ value: this.name, disabled: disabled }, context.getValidation('name').validators], name: [{ value: this.name, disabled: disabled }, context.getValidation('name').validators],
code: [{ value: this.code, disabled: disabled }, context.getValidation('code').validators], code: [{ value: this.code, disabled: !isNew }, context.getValidation('code').validators],
status: [{ value: this.status, disabled: disabled }, context.getValidation('status').validators], status: [{ value: this.status, disabled: disabled }, context.getValidation('status').validators],
hash: [{ value: this.hash, disabled: disabled }, context.getValidation('hash').validators] hash: [{ value: this.hash, disabled: disabled }, context.getValidation('hash').validators]
}); });

View File

@ -30,6 +30,14 @@
<mat-error *ngIf="formGroup.get('label').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error> <mat-error *ngIf="formGroup.get('label').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field> </mat-form-field>
</div> </div>
<div class="col-6">
<mat-form-field class="w-100">
<mat-label>{{'PLAN-BLUEPRINT-EDITOR.FIELDS.CODE' | translate}}</mat-label>
<input matInput type="text" name="CODE" [formControl]="formGroup.get('code')" required>
<mat-error *ngIf="formGroup.get('code').hasError('backendError')">{{formGroup.get('code').getError('backendError').message}}</mat-error>
<mat-error *ngIf="formGroup.get('code').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
</div>
<h4 class="col-12">{{'PLAN-BLUEPRINT-EDITOR.FIELDS.SECTIONS' | translate}} <h4 class="col-12">{{'PLAN-BLUEPRINT-EDITOR.FIELDS.SECTIONS' | translate}}
<mat-error *ngIf="formGroup.get('definition').get('sections').hasError('planBlueprintSystemFieldRequired')"> {{'PLAN-BLUEPRINT-EDITOR.SYSTEM-FIELDS-REQUIRED' | translate}} </mat-error> <mat-error *ngIf="formGroup.get('definition').get('sections').hasError('planBlueprintSystemFieldRequired')"> {{'PLAN-BLUEPRINT-EDITOR.SYSTEM-FIELDS-REQUIRED' | translate}} </mat-error>
</h4> </h4>

View File

@ -195,13 +195,14 @@ export class PlanBlueprintEditorComponent extends BaseEditor<PlanBlueprintEditor
} }
buildForm() { buildForm() {
this.formGroup = this.editorModel.buildForm(null, this.isDeleted || !this.authService.hasPermission(AppPermission.EditPlanBlueprint)); this.formGroup = this.editorModel.buildForm(null, this.isDeleted || !this.authService.hasPermission(AppPermission.EditPlanBlueprint), (this.isNew || this.isClone));
this.planBlueprintEditorService.setValidationErrorModel(this.editorModel.validationErrorModel); this.planBlueprintEditorService.setValidationErrorModel(this.editorModel.validationErrorModel);
if (this.isFinalized || this.isDeleted) { if (this.isFinalized || this.isDeleted) {
this.formGroup.disable(); this.formGroup.disable();
} }
if (this.isNewVersion) { if (this.isNewVersion) {
this.formGroup.enable(); this.formGroup.enable();
this.formGroup.get('code').disable();
} }
} }
@ -211,7 +212,7 @@ export class PlanBlueprintEditorComponent extends BaseEditor<PlanBlueprintEditor
refreshOnNavigateToData(id?: Guid): void { refreshOnNavigateToData(id?: Guid): void {
this.formGroup.markAsPristine(); this.formGroup.markAsPristine();
if (this.isNew || this.isNewVersion) { if (this.isNew || this.isNewVersion || this.isClone) {
let route = []; let route = [];
route.push(this.routerUtils.generateUrl('/plan-blueprints/' + id)); route.push(this.routerUtils.generateUrl('/plan-blueprints/' + id));
this.router.navigate(route, { queryParams: { 'lookup': this.queryParamsService.serializeLookup(this.lookupParams), 'lv': ++this.lv }, replaceUrl: true, relativeTo: this.route }); this.router.navigate(route, { queryParams: { 'lookup': this.queryParamsService.serializeLookup(this.lookupParams), 'lv': ++this.lv }, replaceUrl: true, relativeTo: this.route });
@ -223,6 +224,7 @@ export class PlanBlueprintEditorComponent extends BaseEditor<PlanBlueprintEditor
persistEntity(onSuccess?: (response) => void): void { persistEntity(onSuccess?: (response) => void): void {
if (this.isNewVersion == false) { if (this.isNewVersion == false) {
const formData = this.formService.getValue(this.formGroup.value) as PlanBlueprintPersist; const formData = this.formService.getValue(this.formGroup.value) as PlanBlueprintPersist;
formData.code = this.formGroup.get('code').getRawValue();
this.planBlueprintService.persist(formData) this.planBlueprintService.persist(formData)
.pipe(takeUntil(this._destroyed)).subscribe( .pipe(takeUntil(this._destroyed)).subscribe(

View File

@ -13,6 +13,7 @@ import { Guid } from "@common/types/guid";
export class PlanBlueprintEditorModel extends BaseEditorModel implements PlanBlueprintPersist { export class PlanBlueprintEditorModel extends BaseEditorModel implements PlanBlueprintPersist {
label: string; label: string;
code: string;
definition: PlanBlueprintDefinitionEditorModel = new PlanBlueprintDefinitionEditorModel(); definition: PlanBlueprintDefinitionEditorModel = new PlanBlueprintDefinitionEditorModel();
status: PlanBlueprintStatus = PlanBlueprintStatus.Draft; status: PlanBlueprintStatus = PlanBlueprintStatus.Draft;
versionStatus: PlanBlueprintVersionStatus = PlanBlueprintVersionStatus.Current; versionStatus: PlanBlueprintVersionStatus = PlanBlueprintVersionStatus.Current;
@ -28,6 +29,7 @@ export class PlanBlueprintEditorModel extends BaseEditorModel implements PlanBlu
if (item) { if (item) {
super.fromModel(item); super.fromModel(item);
this.label = item.label; this.label = item.label;
this.code = item.code;
this.status = item.status; this.status = item.status;
this.versionStatus = item.versionStatus; this.versionStatus = item.versionStatus;
this.definition = new PlanBlueprintDefinitionEditorModel(this.validationErrorModel).fromModel(item.definition); this.definition = new PlanBlueprintDefinitionEditorModel(this.validationErrorModel).fromModel(item.definition);
@ -35,12 +37,13 @@ export class PlanBlueprintEditorModel extends BaseEditorModel implements PlanBlu
return this; return this;
} }
buildForm(context: ValidationContext = null, disabled: boolean = false): UntypedFormGroup { buildForm(context: ValidationContext = null, disabled: boolean = false, isNewOrClone: boolean = false): UntypedFormGroup {
if (context == null) { context = this.createValidationContext(); } if (context == null) { context = this.createValidationContext(); }
return this.formBuilder.group({ return this.formBuilder.group({
id: [{ value: this.id, disabled: disabled }, context.getValidation('id').validators], id: [{ value: this.id, disabled: disabled }, context.getValidation('id').validators],
label: [{ value: this.label, disabled: disabled }, context.getValidation('label').validators], label: [{ value: this.label, disabled: disabled }, context.getValidation('label').validators],
code: [{ value: this.code, disabled: !isNewOrClone }, context.getValidation('code').validators],
status: [{ value: this.status, disabled: disabled }, context.getValidation('status').validators], status: [{ value: this.status, disabled: disabled }, context.getValidation('status').validators],
definition: this.definition.buildForm({ definition: this.definition.buildForm({
rootPath: `definition.`, rootPath: `definition.`,
@ -55,6 +58,7 @@ export class PlanBlueprintEditorModel extends BaseEditorModel implements PlanBlu
const baseValidationArray: Validation[] = new Array<Validation>(); const baseValidationArray: Validation[] = new Array<Validation>();
baseValidationArray.push({ key: 'id', validators: [BackendErrorValidator(this.validationErrorModel, 'id')] }); baseValidationArray.push({ key: 'id', validators: [BackendErrorValidator(this.validationErrorModel, 'id')] });
baseValidationArray.push({ key: 'label', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'label')] }); baseValidationArray.push({ key: 'label', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'label')] });
baseValidationArray.push({ key: 'code', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'code')] });
baseValidationArray.push({ key: 'status', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'status')] }); baseValidationArray.push({ key: 'status', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'status')] });
baseValidationArray.push({ key: 'hash', validators: [] }); baseValidationArray.push({ key: 'hash', validators: [] });

View File

@ -22,6 +22,7 @@ export class PlanBlueprintEditorResolver extends BaseEditorResolver {
...BaseEditorResolver.lookupFields(), ...BaseEditorResolver.lookupFields(),
nameof<PlanBlueprint>(x => x.id), nameof<PlanBlueprint>(x => x.id),
nameof<PlanBlueprint>(x => x.label), nameof<PlanBlueprint>(x => x.label),
nameof<PlanBlueprint>(x => x.code),
nameof<PlanBlueprint>(x => x.status), nameof<PlanBlueprint>(x => x.status),
[nameof<PlanBlueprint>(x => x.definition), nameof<PlanBlueprintDefinition>(x => x.sections), nameof<PlanBlueprintDefinitionSection>(x => x.id)].join('.'), [nameof<PlanBlueprint>(x => x.definition), nameof<PlanBlueprintDefinition>(x => x.sections), nameof<PlanBlueprintDefinitionSection>(x => x.id)].join('.'),
[nameof<PlanBlueprint>(x => x.definition), nameof<PlanBlueprintDefinition>(x => x.sections), nameof<PlanBlueprintDefinitionSection>(x => x.label)].join('.'), [nameof<PlanBlueprint>(x => x.definition), nameof<PlanBlueprintDefinition>(x => x.sections), nameof<PlanBlueprintDefinitionSection>(x => x.label)].join('.'),

View File

@ -51,6 +51,7 @@ export class PlanBlueprintListingComponent extends BaseListingComponent<PlanBlue
private readonly lookupFields: string[] = [ private readonly lookupFields: string[] = [
nameof<PlanBlueprint>(x => x.id), nameof<PlanBlueprint>(x => x.id),
nameof<PlanBlueprint>(x => x.label), nameof<PlanBlueprint>(x => x.label),
nameof<PlanBlueprint>(x => x.code),
nameof<PlanBlueprint>(x => x.status), nameof<PlanBlueprint>(x => x.status),
nameof<PlanBlueprint>(x => x.version), nameof<PlanBlueprint>(x => x.version),
nameof<PlanBlueprint>(x => x.groupId), nameof<PlanBlueprint>(x => x.groupId),
@ -118,6 +119,11 @@ export class PlanBlueprintListingComponent extends BaseListingComponent<PlanBlue
sortable: true, sortable: true,
languageName: 'PLAN-BLUEPRINT-LISTING.FIELDS.NAME' languageName: 'PLAN-BLUEPRINT-LISTING.FIELDS.NAME'
}, },
{
prop: nameof<PlanBlueprint>(x => x.code),
sortable: true,
languageName: 'PLAN-BLUEPRINT-LISTING.FIELDS.CODE'
},
{ {
prop: nameof<PlanBlueprint>(x => x.status), prop: nameof<PlanBlueprint>(x => x.status),
sortable: true, sortable: true,

View File

@ -25,6 +25,8 @@ export class HttpErrorHandlingService {
this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.BACKEND-ERRORS.REFERENCE-TYPE-IMPORT-NOT-FOUND', { 'referenceTypeCode': errorResponse.error.error }), SnackBarNotificationLevel.Error); this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.BACKEND-ERRORS.REFERENCE-TYPE-IMPORT-NOT-FOUND', { 'referenceTypeCode': errorResponse.error.error }), SnackBarNotificationLevel.Error);
} if (errorResponse.error.code === ResponseErrorCode.descriptionTemplateImportNotFound){ } if (errorResponse.error.code === ResponseErrorCode.descriptionTemplateImportNotFound){
this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.BACKEND-ERRORS.DESCRIPTION-TEMPLATE-IMPORT-NOT-FOUND', { 'descriptionTemplateLabel': errorResponse.error.error }), SnackBarNotificationLevel.Error); this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.BACKEND-ERRORS.DESCRIPTION-TEMPLATE-IMPORT-NOT-FOUND', { 'descriptionTemplateLabel': errorResponse.error.error }), SnackBarNotificationLevel.Error);
} if (errorResponse.error.code === ResponseErrorCode.planBlueprintImportNotFound){
this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.BACKEND-ERRORS.PLAN-BLUEPRINT-IMPORT-NOT-FOUND', { 'planBlueprintLabel': errorResponse.error.error }), SnackBarNotificationLevel.Error);
} else { } else {
this.uiNotificationService.snackBarNotification(ResponseErrorCodeHelper.getErrorMessageByBackendStatusCode(errorResponse.error.code, this.language), SnackBarNotificationLevel.Error); this.uiNotificationService.snackBarNotification(ResponseErrorCodeHelper.getErrorMessageByBackendStatusCode(errorResponse.error.code, this.language), SnackBarNotificationLevel.Error);
} }