add description status logic
This commit is contained in:
parent
99023ed159
commit
4dc0927140
|
@ -39,6 +39,10 @@ public class DescriptionEntity extends TenantScopedBaseEntity {
|
||||||
private DescriptionStatus status;
|
private DescriptionStatus status;
|
||||||
public static final String _status = "status";
|
public static final String _status = "status";
|
||||||
|
|
||||||
|
@Column(name = "status_id", nullable = true)
|
||||||
|
private UUID statusId;
|
||||||
|
public static final String _statusId = "statusId";
|
||||||
|
|
||||||
@Column(name = "description")
|
@Column(name = "description")
|
||||||
private String description;
|
private String description;
|
||||||
|
|
||||||
|
@ -187,5 +191,13 @@ public class DescriptionEntity extends TenantScopedBaseEntity {
|
||||||
public void setDescriptionTemplateId(UUID descriptionTemplateId) {
|
public void setDescriptionTemplateId(UUID descriptionTemplateId) {
|
||||||
this.descriptionTemplateId = descriptionTemplateId;
|
this.descriptionTemplateId = descriptionTemplateId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public UUID getStatusId() {
|
||||||
|
return statusId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatusId(UUID statusId) {
|
||||||
|
this.statusId = statusId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package org.opencdmp.model;
|
package org.opencdmp.model;
|
||||||
|
|
||||||
import org.opencdmp.commons.enums.DescriptionStatus;
|
|
||||||
|
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
@ -15,7 +14,7 @@ public class PublicDescription {
|
||||||
|
|
||||||
public static final String _label = "label";
|
public static final String _label = "label";
|
||||||
|
|
||||||
private DescriptionStatus status;
|
private PublicDescriptionStatus status;
|
||||||
|
|
||||||
public static final String _status = "status";
|
public static final String _status = "status";
|
||||||
|
|
||||||
|
@ -65,11 +64,11 @@ public class PublicDescription {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public DescriptionStatus getStatus() {
|
public PublicDescriptionStatus getStatus() {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setStatus(DescriptionStatus status) {
|
public void setStatus(PublicDescriptionStatus status) {
|
||||||
this.status = status;
|
this.status = status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
package org.opencdmp.model;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class PublicDescriptionStatus {
|
||||||
|
|
||||||
|
public final static String _id = "id";
|
||||||
|
private UUID id;
|
||||||
|
|
||||||
|
public final static String _name = "name";
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public final static String _internalStatus = "internalStatus";
|
||||||
|
private org.opencdmp.commons.enums.DescriptionStatus internalStatus;
|
||||||
|
|
||||||
|
public UUID getId() { return this.id; }
|
||||||
|
public void setId(UUID id) { this.id = id; }
|
||||||
|
|
||||||
|
public String getName() { return this.name; }
|
||||||
|
public void setName(String name) { this.name = name; }
|
||||||
|
|
||||||
|
public org.opencdmp.commons.enums.DescriptionStatus getInternalStatus() { return this.internalStatus; }
|
||||||
|
public void setInternalStatus(org.opencdmp.commons.enums.DescriptionStatus internalStatus) { this.internalStatus = internalStatus; }
|
||||||
|
}
|
|
@ -10,10 +10,8 @@ import gr.cite.tools.logging.LoggerService;
|
||||||
import org.opencdmp.authorization.AuthorizationFlags;
|
import org.opencdmp.authorization.AuthorizationFlags;
|
||||||
import org.opencdmp.convention.ConventionService;
|
import org.opencdmp.convention.ConventionService;
|
||||||
import org.opencdmp.data.DescriptionEntity;
|
import org.opencdmp.data.DescriptionEntity;
|
||||||
import org.opencdmp.model.PublicDescription;
|
import org.opencdmp.model.*;
|
||||||
import org.opencdmp.model.PublicDescriptionTemplate;
|
import org.opencdmp.query.DescriptionStatusQuery;
|
||||||
import org.opencdmp.model.PublicPlan;
|
|
||||||
import org.opencdmp.model.PublicPlanDescriptionTemplate;
|
|
||||||
import org.opencdmp.query.DescriptionTemplateQuery;
|
import org.opencdmp.query.DescriptionTemplateQuery;
|
||||||
import org.opencdmp.query.PlanDescriptionTemplateQuery;
|
import org.opencdmp.query.PlanDescriptionTemplateQuery;
|
||||||
import org.opencdmp.query.PlanQuery;
|
import org.opencdmp.query.PlanQuery;
|
||||||
|
@ -66,12 +64,15 @@ public class PublicDescriptionBuilder extends BaseBuilder<PublicDescription, Des
|
||||||
FieldSet planFields = fields.extractPrefixed(this.asPrefix(PublicDescription._plan));
|
FieldSet planFields = fields.extractPrefixed(this.asPrefix(PublicDescription._plan));
|
||||||
Map<UUID, PublicPlan> planItemsMap = this.collectPlans(planFields, data);
|
Map<UUID, PublicPlan> planItemsMap = this.collectPlans(planFields, data);
|
||||||
|
|
||||||
|
FieldSet descriptionStatusFields = fields.extractPrefixed(this.asPrefix(PublicDescription._status));
|
||||||
|
Map<UUID, PublicDescriptionStatus> descriptionStatusItemsMap = this.collectDescriptionStatuses(descriptionStatusFields, data);
|
||||||
|
|
||||||
List<PublicDescription> models = new ArrayList<>();
|
List<PublicDescription> models = new ArrayList<>();
|
||||||
for (DescriptionEntity d : data) {
|
for (DescriptionEntity d : data) {
|
||||||
PublicDescription m = new PublicDescription();
|
PublicDescription m = new PublicDescription();
|
||||||
if (fields.hasField(this.asIndexer(PublicDescription._id))) m.setId(d.getId());
|
if (fields.hasField(this.asIndexer(PublicDescription._id))) m.setId(d.getId());
|
||||||
if (fields.hasField(this.asIndexer(PublicDescription._label))) m.setLabel(d.getLabel());
|
if (fields.hasField(this.asIndexer(PublicDescription._label))) m.setLabel(d.getLabel());
|
||||||
if (fields.hasField(this.asIndexer(PublicDescription._status))) m.setStatus(d.getStatus());
|
if (!descriptionStatusFields.isEmpty() && descriptionStatusItemsMap != null && descriptionStatusItemsMap.containsKey(d.getStatusId())) m.setStatus(descriptionStatusItemsMap.get(d.getStatusId()));
|
||||||
if (fields.hasField(this.asIndexer(PublicDescription._description))) m.setDescription(d.getDescription());
|
if (fields.hasField(this.asIndexer(PublicDescription._description))) m.setDescription(d.getDescription());
|
||||||
if (fields.hasField(this.asIndexer(PublicDescription._createdAt))) m.setCreatedAt(d.getCreatedAt());
|
if (fields.hasField(this.asIndexer(PublicDescription._createdAt))) m.setCreatedAt(d.getCreatedAt());
|
||||||
if (fields.hasField(this.asIndexer(PublicDescription._updatedAt))) m.setUpdatedAt(d.getUpdatedAt());
|
if (fields.hasField(this.asIndexer(PublicDescription._updatedAt))) m.setUpdatedAt(d.getUpdatedAt());
|
||||||
|
@ -177,4 +178,34 @@ public class PublicDescriptionBuilder extends BaseBuilder<PublicDescription, Des
|
||||||
return itemMap;
|
return itemMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Map<UUID, PublicDescriptionStatus> collectDescriptionStatuses(FieldSet fields, List<DescriptionEntity> data) throws MyApplicationException {
|
||||||
|
if (fields.isEmpty() || data.isEmpty())
|
||||||
|
return null;
|
||||||
|
this.logger.debug("checking related - {}", PublicDescriptionStatus.class.getSimpleName());
|
||||||
|
|
||||||
|
Map<UUID, PublicDescriptionStatus> itemMap;
|
||||||
|
if (!fields.hasOtherField(this.asIndexer(PublicDescriptionStatus._id))) {
|
||||||
|
itemMap = this.asEmpty(
|
||||||
|
data.stream().map(DescriptionEntity::getDescriptionTemplateId).distinct().collect(Collectors.toList()),
|
||||||
|
x -> {
|
||||||
|
PublicDescriptionStatus item = new PublicDescriptionStatus();
|
||||||
|
item.setId(x);
|
||||||
|
return item;
|
||||||
|
},
|
||||||
|
PublicDescriptionStatus::getId);
|
||||||
|
} else {
|
||||||
|
FieldSet clone = new BaseFieldSet(fields.getFields()).ensure(PublicDescriptionStatus._id);
|
||||||
|
DescriptionStatusQuery q = this.queryFactory.query(DescriptionStatusQuery.class).disableTracking().authorize(this.authorize).ids(data.stream().map(DescriptionEntity::getStatusId).distinct().collect(Collectors.toList()));
|
||||||
|
itemMap = this.builderFactory.builder(PublicDescriptionStatusBuilder.class).authorize(this.authorize).asForeignKey(q, clone, PublicDescriptionStatus::getId);
|
||||||
|
}
|
||||||
|
if (!fields.hasField(PublicDescriptionStatus._id)) {
|
||||||
|
itemMap.forEach((id, item) -> {
|
||||||
|
if (item != null)
|
||||||
|
item.setId(null);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return itemMap;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
package org.opencdmp.model.builder;
|
||||||
|
|
||||||
|
import gr.cite.tools.exception.MyApplicationException;
|
||||||
|
import gr.cite.tools.fieldset.FieldSet;
|
||||||
|
import gr.cite.tools.logging.DataLogEntry;
|
||||||
|
import gr.cite.tools.logging.LoggerService;
|
||||||
|
import org.opencdmp.authorization.AuthorizationFlags;
|
||||||
|
import org.opencdmp.convention.ConventionService;
|
||||||
|
|
||||||
|
|
||||||
|
import org.opencdmp.data.DescriptionStatusEntity;
|
||||||
|
import org.opencdmp.model.PublicDescriptionStatus;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||||
|
import org.springframework.context.annotation.Scope;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||||
|
public class PublicDescriptionStatusBuilder extends BaseBuilder<PublicDescriptionStatus, DescriptionStatusEntity> {
|
||||||
|
|
||||||
|
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
|
||||||
|
@Autowired
|
||||||
|
public PublicDescriptionStatusBuilder(
|
||||||
|
ConventionService conventionService) {
|
||||||
|
super(conventionService, new LoggerService(LoggerFactory.getLogger(PublicDescriptionStatusBuilder.class)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public PublicDescriptionStatusBuilder authorize(EnumSet<AuthorizationFlags> values) {
|
||||||
|
this.authorize = values;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<PublicDescriptionStatus> build(FieldSet fields, List<DescriptionStatusEntity> data) throws MyApplicationException {
|
||||||
|
this.logger.debug("building for {} items requesting {} fields", Optional.ofNullable(data).map(List::size).orElse(0), Optional.ofNullable(fields).map(FieldSet::getFields).map(Set::size).orElse(0));
|
||||||
|
this.logger.trace(new DataLogEntry("requested fields", fields));
|
||||||
|
if (fields == null || data == null || fields.isEmpty())
|
||||||
|
return new ArrayList<>();
|
||||||
|
List<PublicDescriptionStatus> models = new ArrayList<>();
|
||||||
|
for (DescriptionStatusEntity d : data) {
|
||||||
|
PublicDescriptionStatus m = new PublicDescriptionStatus();
|
||||||
|
if (fields.hasField(this.asIndexer(PublicDescriptionStatus._id))) m.setId(d.getId());
|
||||||
|
if (fields.hasField(this.asIndexer(PublicDescriptionStatus._name))) m.setName(d.getName());
|
||||||
|
if (fields.hasField(this.asIndexer(PublicDescriptionStatus._internalStatus))) m.setInternalStatus(d.getInternalStatus());
|
||||||
|
models.add(m);
|
||||||
|
}
|
||||||
|
this.logger.debug("build {} items", Optional.of(models).map(List::size).orElse(0));
|
||||||
|
return models;
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,10 +26,12 @@ import org.opencdmp.model.builder.DescriptionTagBuilder;
|
||||||
import org.opencdmp.model.builder.PlanDescriptionTemplateBuilder;
|
import org.opencdmp.model.builder.PlanDescriptionTemplateBuilder;
|
||||||
import org.opencdmp.model.builder.UserBuilder;
|
import org.opencdmp.model.builder.UserBuilder;
|
||||||
import org.opencdmp.model.builder.descriptionreference.DescriptionReferenceBuilder;
|
import org.opencdmp.model.builder.descriptionreference.DescriptionReferenceBuilder;
|
||||||
|
import org.opencdmp.model.builder.descriptionstatus.DescriptionStatusBuilder;
|
||||||
import org.opencdmp.model.builder.descriptiontemplate.DescriptionTemplateBuilder;
|
import org.opencdmp.model.builder.descriptiontemplate.DescriptionTemplateBuilder;
|
||||||
import org.opencdmp.model.builder.plan.PlanBuilder;
|
import org.opencdmp.model.builder.plan.PlanBuilder;
|
||||||
import org.opencdmp.model.description.Description;
|
import org.opencdmp.model.description.Description;
|
||||||
import org.opencdmp.model.descriptionreference.DescriptionReference;
|
import org.opencdmp.model.descriptionreference.DescriptionReference;
|
||||||
|
import org.opencdmp.model.descriptionstatus.DescriptionStatus;
|
||||||
import org.opencdmp.model.descriptiontemplate.DescriptionTemplate;
|
import org.opencdmp.model.descriptiontemplate.DescriptionTemplate;
|
||||||
import org.opencdmp.model.plan.Plan;
|
import org.opencdmp.model.plan.Plan;
|
||||||
import org.opencdmp.model.user.User;
|
import org.opencdmp.model.user.User;
|
||||||
|
@ -85,6 +87,9 @@ public class DescriptionBuilder extends BaseBuilder<Description, DescriptionEnti
|
||||||
if (fields == null || data == null || fields.isEmpty())
|
if (fields == null || data == null || fields.isEmpty())
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
|
|
||||||
|
FieldSet statusFields = fields.extractPrefixed(this.asPrefix(Description._status));
|
||||||
|
Map<UUID, DescriptionStatus> statusItemsMap = this.collectDescriptionStatuses(statusFields, data);
|
||||||
|
|
||||||
FieldSet planDescriptionTemplateFields = fields.extractPrefixed(this.asPrefix(Description._planDescriptionTemplate));
|
FieldSet planDescriptionTemplateFields = fields.extractPrefixed(this.asPrefix(Description._planDescriptionTemplate));
|
||||||
Map<UUID, PlanDescriptionTemplate> planDescriptionTemplateItemsMap = this.collectPlanDescriptionTemplates(planDescriptionTemplateFields, data);
|
Map<UUID, PlanDescriptionTemplate> planDescriptionTemplateItemsMap = this.collectPlanDescriptionTemplates(planDescriptionTemplateFields, data);
|
||||||
|
|
||||||
|
@ -116,7 +121,7 @@ public class DescriptionBuilder extends BaseBuilder<Description, DescriptionEnti
|
||||||
if (fields.hasField(this.asIndexer(Description._id))) m.setId(d.getId());
|
if (fields.hasField(this.asIndexer(Description._id))) m.setId(d.getId());
|
||||||
if (fields.hasField(this.asIndexer(Description._tenantId))) m.setTenantId(d.getTenantId());
|
if (fields.hasField(this.asIndexer(Description._tenantId))) m.setTenantId(d.getTenantId());
|
||||||
if (fields.hasField(this.asIndexer(Description._label))) m.setLabel(d.getLabel());
|
if (fields.hasField(this.asIndexer(Description._label))) m.setLabel(d.getLabel());
|
||||||
if (fields.hasField(this.asIndexer(Description._status))) m.setStatus(d.getStatus());
|
if (!statusFields.isEmpty() && statusItemsMap != null && statusItemsMap.containsKey(d.getStatusId())) m.setStatus(statusItemsMap.get(d.getStatusId()));
|
||||||
if (fields.hasField(this.asIndexer(Description._description))) m.setDescription(d.getDescription());
|
if (fields.hasField(this.asIndexer(Description._description))) m.setDescription(d.getDescription());
|
||||||
if (fields.hasField(this.asIndexer(Description._createdAt))) m.setCreatedAt(d.getCreatedAt());
|
if (fields.hasField(this.asIndexer(Description._createdAt))) m.setCreatedAt(d.getCreatedAt());
|
||||||
if (fields.hasField(this.asIndexer(Description._updatedAt))) m.setUpdatedAt(d.getUpdatedAt());
|
if (fields.hasField(this.asIndexer(Description._updatedAt))) m.setUpdatedAt(d.getUpdatedAt());
|
||||||
|
@ -143,6 +148,36 @@ public class DescriptionBuilder extends BaseBuilder<Description, DescriptionEnti
|
||||||
return models;
|
return models;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Map<UUID, DescriptionStatus> collectDescriptionStatuses(FieldSet fields, List<DescriptionEntity> data) throws MyApplicationException {
|
||||||
|
if (fields.isEmpty() || data.isEmpty())
|
||||||
|
return null;
|
||||||
|
this.logger.debug("checking related - {}", DescriptionStatus.class.getSimpleName());
|
||||||
|
|
||||||
|
Map<UUID, DescriptionStatus> itemMap;
|
||||||
|
if (!fields.hasOtherField(this.asIndexer(DescriptionStatus._id))) {
|
||||||
|
itemMap = this.asEmpty(
|
||||||
|
data.stream().map(DescriptionEntity::getStatusId).distinct().collect(Collectors.toList()),
|
||||||
|
x -> {
|
||||||
|
DescriptionStatus item = new DescriptionStatus();
|
||||||
|
item.setId(x);
|
||||||
|
return item;
|
||||||
|
},
|
||||||
|
DescriptionStatus::getId);
|
||||||
|
} else {
|
||||||
|
FieldSet clone = new BaseFieldSet(fields.getFields()).ensure(DescriptionStatus._id);
|
||||||
|
DescriptionStatusQuery q = this.queryFactory.query(DescriptionStatusQuery.class).disableTracking().authorize(this.authorize).ids(data.stream().map(DescriptionEntity::getStatusId).distinct().collect(Collectors.toList()));
|
||||||
|
itemMap = this.builderFactory.builder(DescriptionStatusBuilder.class).authorize(this.authorize).asForeignKey(q, clone, DescriptionStatus::getId);
|
||||||
|
}
|
||||||
|
if (!fields.hasField(DescriptionStatus._id)) {
|
||||||
|
itemMap.forEach((id, item) -> {
|
||||||
|
if (item != null)
|
||||||
|
item.setId(null);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return itemMap;
|
||||||
|
}
|
||||||
|
|
||||||
private Map<UUID, User> collectUsers(FieldSet fields, List<DescriptionEntity> data) throws MyApplicationException {
|
private Map<UUID, User> collectUsers(FieldSet fields, List<DescriptionEntity> data) throws MyApplicationException {
|
||||||
if (fields.isEmpty() || data.isEmpty())
|
if (fields.isEmpty() || data.isEmpty())
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package org.opencdmp.model.description;
|
package org.opencdmp.model.description;
|
||||||
|
|
||||||
import org.opencdmp.commons.enums.DescriptionStatus;
|
import org.opencdmp.model.descriptionstatus.DescriptionStatus;
|
||||||
import org.opencdmp.commons.enums.IsActive;
|
import org.opencdmp.commons.enums.IsActive;
|
||||||
import org.opencdmp.model.*;
|
import org.opencdmp.model.*;
|
||||||
import org.opencdmp.model.descriptionreference.DescriptionReference;
|
import org.opencdmp.model.descriptionreference.DescriptionReference;
|
||||||
|
|
|
@ -30,7 +30,7 @@ public class DescriptionToPublicApiDatasetMapper {
|
||||||
model.setDescription(description.getDescription());
|
model.setDescription(description.getDescription());
|
||||||
model.setReference("");
|
model.setReference("");
|
||||||
model.setUri("");
|
model.setUri("");
|
||||||
model.setStatus(description.getStatus());
|
// TODO status model.setStatus(description.getStatus());
|
||||||
|
|
||||||
model.setDmp(dmp);
|
model.setDmp(dmp);
|
||||||
model.setDatasetProfileDefinition(descriptionTemplateToPublicApiDatasetProfileMapper.toPublicModel(description.getDescriptionTemplate()));
|
model.setDatasetProfileDefinition(descriptionTemplateToPublicApiDatasetProfileMapper.toPublicModel(description.getDescriptionTemplate()));
|
||||||
|
|
|
@ -46,9 +46,9 @@ public class DescriptionPersist {
|
||||||
|
|
||||||
public static final String _descriptionTemplateId = "descriptionTemplateId";
|
public static final String _descriptionTemplateId = "descriptionTemplateId";
|
||||||
|
|
||||||
private DescriptionStatus status;
|
private UUID statusId;
|
||||||
|
|
||||||
public static final String _status = "status";
|
public static final String _statusId = "statusId";
|
||||||
|
|
||||||
private String description;
|
private String description;
|
||||||
|
|
||||||
|
@ -97,12 +97,12 @@ public class DescriptionPersist {
|
||||||
this.planDescriptionTemplateId = planDescriptionTemplateId;
|
this.planDescriptionTemplateId = planDescriptionTemplateId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DescriptionStatus getStatus() {
|
public UUID getStatusId() {
|
||||||
return this.status;
|
return statusId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setStatus(DescriptionStatus status) {
|
public void setStatusId(UUID statusId) {
|
||||||
this.status = status;
|
this.statusId = statusId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDescription() {
|
public String getDescription() {
|
||||||
|
@ -178,16 +178,19 @@ public class DescriptionPersist {
|
||||||
DescriptionTemplateEntity descriptionTemplate = null;
|
DescriptionTemplateEntity descriptionTemplate = null;
|
||||||
PlanEntity planEntity = null;
|
PlanEntity planEntity = null;
|
||||||
PlanBlueprintEntity planBlueprintEntity = null;
|
PlanBlueprintEntity planBlueprintEntity = null;
|
||||||
|
DescriptionStatusEntity statusEntity = null;
|
||||||
try {
|
try {
|
||||||
descriptionTemplate = this.isValidGuid(item.getDescriptionTemplateId()) ? this.entityManager.find(DescriptionTemplateEntity.class, item.getDescriptionTemplateId(), true) : null;
|
descriptionTemplate = this.isValidGuid(item.getDescriptionTemplateId()) ? this.entityManager.find(DescriptionTemplateEntity.class, item.getDescriptionTemplateId(), true) : null;
|
||||||
planEntity = this.isValidGuid(item.getPlanId()) ? this.entityManager.find(PlanEntity.class, item.getPlanId(), true) : null;
|
planEntity = this.isValidGuid(item.getPlanId()) ? this.entityManager.find(PlanEntity.class, item.getPlanId(), true) : null;
|
||||||
planBlueprintEntity = planEntity == null ? null : this.entityManager.find(PlanBlueprintEntity.class, planEntity.getBlueprintId());
|
planBlueprintEntity = planEntity == null ? null : this.entityManager.find(PlanBlueprintEntity.class, planEntity.getBlueprintId());
|
||||||
|
statusEntity = this.isValidGuid(item.getStatusId()) ? this.entityManager.find(DescriptionStatusEntity.class, item.getStatusId(), true) : null;
|
||||||
|
|
||||||
} catch (InvalidApplicationException e) {
|
} catch (InvalidApplicationException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
DefinitionEntity definition = descriptionTemplate == null ? null : this.xmlHandlingService.fromXmlSafe(DefinitionEntity.class, descriptionTemplate.getDefinition());
|
DefinitionEntity definition = descriptionTemplate == null ? null : this.xmlHandlingService.fromXmlSafe(DefinitionEntity.class, descriptionTemplate.getDefinition());
|
||||||
PlanBlueprintEntity finalPlanBlueprintEntity = planBlueprintEntity;
|
PlanBlueprintEntity finalPlanBlueprintEntity = planBlueprintEntity;
|
||||||
|
DescriptionStatusEntity finalStatusEntity = statusEntity;
|
||||||
return Arrays.asList(
|
return Arrays.asList(
|
||||||
this.spec()
|
this.spec()
|
||||||
.iff(() -> this.isValidGuid(item.getId()))
|
.iff(() -> this.isValidGuid(item.getId()))
|
||||||
|
@ -214,21 +217,22 @@ public class DescriptionPersist {
|
||||||
.must(() -> this.isValidGuid(item.getPlanDescriptionTemplateId()))
|
.must(() -> this.isValidGuid(item.getPlanDescriptionTemplateId()))
|
||||||
.failOn(DescriptionPersist._planDescriptionTemplateId).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{DescriptionPersist._planDescriptionTemplateId}, LocaleContextHolder.getLocale())),
|
.failOn(DescriptionPersist._planDescriptionTemplateId).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{DescriptionPersist._planDescriptionTemplateId}, LocaleContextHolder.getLocale())),
|
||||||
this.spec()
|
this.spec()
|
||||||
.must(() -> !this.isNull(item.getStatus()))
|
.iff(() -> this.isValidGuid(item.getId()))
|
||||||
.failOn(DescriptionPersist._status).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{DescriptionPersist._status}, LocaleContextHolder.getLocale())),
|
.must(() -> this.isValidGuid(item.getStatusId()))
|
||||||
|
.failOn(DescriptionPersist._statusId).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{DescriptionPersist._statusId}, LocaleContextHolder.getLocale())),
|
||||||
this.spec()
|
this.spec()
|
||||||
.iff(() -> item.getStatus() == DescriptionStatus.Finalized)
|
.iff(() -> finalStatusEntity != null && finalStatusEntity.getInternalStatus() != null && finalStatusEntity.getInternalStatus() == DescriptionStatus.Finalized)
|
||||||
.must(() -> !this.isNull(item.getProperties()))
|
.must(() -> !this.isNull(item.getProperties()))
|
||||||
.failOn(DescriptionPersist._properties).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{DescriptionPersist._properties}, LocaleContextHolder.getLocale())),
|
.failOn(DescriptionPersist._properties).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{DescriptionPersist._properties}, LocaleContextHolder.getLocale())),
|
||||||
this.spec()
|
this.spec()
|
||||||
.iff(() -> item.getStatus() == DescriptionStatus.Finalized)
|
.iff(() -> finalStatusEntity != null && finalStatusEntity.getInternalStatus() != null && finalStatusEntity.getInternalStatus() == DescriptionStatus.Finalized)
|
||||||
.must(() -> this.isDescriptionTemplateMaxMultiplicityValid(finalPlanBlueprintEntity, item.getPlanId(), item.getPlanDescriptionTemplateId(), this.isValidGuid(item.getId())))
|
.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())),
|
.failOn(DescriptionPersist._descriptionTemplateId).failWith(this.messageSource.getMessage("Validation.InvalidDescriptionTemplateMultiplicity", new Object[]{DescriptionPersist._descriptionTemplateId}, LocaleContextHolder.getLocale())),
|
||||||
this.refSpec()
|
this.refSpec()
|
||||||
.iff(() -> item.getStatus() == DescriptionStatus.Finalized)
|
.iff(() -> finalStatusEntity != null && finalStatusEntity.getInternalStatus() != null && finalStatusEntity.getInternalStatus() == DescriptionStatus.Finalized)
|
||||||
.on(DescriptionPersist._properties)
|
.on(DescriptionPersist._properties)
|
||||||
.over(item.getProperties())
|
.over(item.getProperties())
|
||||||
.using(() -> this.validatorFactory.validator(PropertyDefinitionPersist.PropertyDefinitionPersistValidator.class).setStatus(item.getStatus()).withDefinition(definition).setVisibilityService(definition, item.getProperties()))
|
.using(() -> this.validatorFactory.validator(PropertyDefinitionPersist.PropertyDefinitionPersistValidator.class).setStatus(finalStatusEntity.getInternalStatus()).withDefinition(definition).setVisibilityService(definition, item.getProperties()))
|
||||||
// this.navSpec()
|
// this.navSpec()
|
||||||
// .iff(() -> !this.isNull(item.getTags()))
|
// .iff(() -> !this.isNull(item.getTags()))
|
||||||
// .on(DescriptionPersist._tags)
|
// .on(DescriptionPersist._tags)
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package org.opencdmp.model.persist;
|
package org.opencdmp.model.persist;
|
||||||
|
|
||||||
import org.opencdmp.commons.enums.DescriptionStatus;
|
|
||||||
import org.opencdmp.commons.validation.BaseValidator;
|
import org.opencdmp.commons.validation.BaseValidator;
|
||||||
import gr.cite.tools.validation.specification.Specification;
|
import gr.cite.tools.validation.specification.Specification;
|
||||||
import org.opencdmp.convention.ConventionService;
|
import org.opencdmp.convention.ConventionService;
|
||||||
|
@ -21,7 +20,7 @@ public class DescriptionStatusPersist {
|
||||||
|
|
||||||
public static final String _id = "id";
|
public static final String _id = "id";
|
||||||
|
|
||||||
private DescriptionStatus status;
|
private UUID statusId;
|
||||||
|
|
||||||
public static final String _status = "status";
|
public static final String _status = "status";
|
||||||
|
|
||||||
|
@ -37,12 +36,12 @@ public class DescriptionStatusPersist {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DescriptionStatus getStatus() {
|
public UUID getStatusId() {
|
||||||
return status;
|
return statusId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setStatus(DescriptionStatus status) {
|
public void setStatusId(UUID statusId) {
|
||||||
this.status = status;
|
this.statusId = statusId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getHash() {
|
public String getHash() {
|
||||||
|
@ -82,7 +81,7 @@ public class DescriptionStatusPersist {
|
||||||
.must(() -> this.isValidHash(item.getHash()))
|
.must(() -> this.isValidHash(item.getHash()))
|
||||||
.failOn(DescriptionStatusPersist._hash).failWith(messageSource.getMessage("Validation_Required", new Object[]{DescriptionStatusPersist._hash}, LocaleContextHolder.getLocale())),
|
.failOn(DescriptionStatusPersist._hash).failWith(messageSource.getMessage("Validation_Required", new Object[]{DescriptionStatusPersist._hash}, LocaleContextHolder.getLocale())),
|
||||||
this.spec()
|
this.spec()
|
||||||
.must(() -> !this.isNull(item.getStatus()))
|
.must(() -> this.isValidGuid(item.getStatusId()))
|
||||||
.failOn(DescriptionStatusPersist._status).failWith(messageSource.getMessage("Validation_Required", new Object[]{DescriptionStatusPersist._status}, LocaleContextHolder.getLocale()))
|
.failOn(DescriptionStatusPersist._status).failWith(messageSource.getMessage("Validation_Required", new Object[]{DescriptionStatusPersist._status}, LocaleContextHolder.getLocale()))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -400,6 +400,8 @@ public class DescriptionQuery extends QueryBase<DescriptionEntity> {
|
||||||
return DescriptionEntity._properties;
|
return DescriptionEntity._properties;
|
||||||
else if (item.match(Description._status) || item.match(PublicDescription._status))
|
else if (item.match(Description._status) || item.match(PublicDescription._status))
|
||||||
return DescriptionEntity._status;
|
return DescriptionEntity._status;
|
||||||
|
else if (item.prefix(Description._status) || item.prefix(PublicDescription._status))
|
||||||
|
return DescriptionEntity._statusId;
|
||||||
else if (item.match(Description._description) || item.match(PublicDescription._description))
|
else if (item.match(Description._description) || item.match(PublicDescription._description))
|
||||||
return DescriptionEntity._description;
|
return DescriptionEntity._description;
|
||||||
else if (item.match(Description._createdBy))
|
else if (item.match(Description._createdBy))
|
||||||
|
@ -444,6 +446,7 @@ public class DescriptionQuery extends QueryBase<DescriptionEntity> {
|
||||||
item.setLabel(QueryBase.convertSafe(tuple, columns, DescriptionEntity._label, String.class));
|
item.setLabel(QueryBase.convertSafe(tuple, columns, DescriptionEntity._label, String.class));
|
||||||
item.setProperties(QueryBase.convertSafe(tuple, columns, DescriptionEntity._properties, String.class));
|
item.setProperties(QueryBase.convertSafe(tuple, columns, DescriptionEntity._properties, String.class));
|
||||||
item.setStatus(QueryBase.convertSafe(tuple, columns, DescriptionEntity._status, DescriptionStatus.class));
|
item.setStatus(QueryBase.convertSafe(tuple, columns, DescriptionEntity._status, DescriptionStatus.class));
|
||||||
|
item.setStatusId(QueryBase.convertSafe(tuple, columns, DescriptionEntity._statusId, UUID.class));
|
||||||
item.setDescription(QueryBase.convertSafe(tuple, columns, DescriptionEntity._description, String.class));
|
item.setDescription(QueryBase.convertSafe(tuple, columns, DescriptionEntity._description, String.class));
|
||||||
item.setCreatedAt(QueryBase.convertSafe(tuple, columns, DescriptionEntity._createdAt, Instant.class));
|
item.setCreatedAt(QueryBase.convertSafe(tuple, columns, DescriptionEntity._createdAt, Instant.class));
|
||||||
item.setUpdatedAt(QueryBase.convertSafe(tuple, columns, DescriptionEntity._updatedAt, Instant.class));
|
item.setUpdatedAt(QueryBase.convertSafe(tuple, columns, DescriptionEntity._updatedAt, Instant.class));
|
||||||
|
|
|
@ -77,9 +77,9 @@ public class DashboardServiceImpl implements DashboardService {
|
||||||
descriptionLookup.getPage().setOffset(0);
|
descriptionLookup.getPage().setOffset(0);
|
||||||
descriptionLookup.getPage().setSize(model.getPage().getSize()+model.getPage().getOffset());
|
descriptionLookup.getPage().setSize(model.getPage().getSize()+model.getPage().getOffset());
|
||||||
|
|
||||||
QueryResult<Description> descriptions = this.elasticQueryHelperService.collect(descriptionLookup, AuthorizationFlags.AllExceptPublic, new BaseFieldSet().ensure(Description._id).ensure(Description._updatedAt).ensure(Description._status).ensure(Description._label));
|
QueryResult<Description> descriptions = this.elasticQueryHelperService.collect(descriptionLookup, AuthorizationFlags.AllExceptPublic, new BaseFieldSet().ensure(Description._id).ensure(Description._updatedAt).ensure(String.join(".",Description._status, org.opencdmp.model.descriptionstatus.DescriptionStatus._internalStatus)).ensure(Description._label));
|
||||||
if (!this.conventionService.isListNullOrEmpty(descriptions.getItems())) {
|
if (!this.conventionService.isListNullOrEmpty(descriptions.getItems())) {
|
||||||
for (Description description : descriptions.getItems()) recentActivityItemEntities.add(new RecentActivityItemEntity(RecentActivityItemType.Description, description.getId(), description.getUpdatedAt(), description.getLabel(), description.getStatus().getValue()));
|
for (Description description : descriptions.getItems()) recentActivityItemEntities.add(new RecentActivityItemEntity(RecentActivityItemType.Description, description.getId(), description.getUpdatedAt(), description.getLabel(), description.getStatus().getInternalStatus().getValue()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,7 @@ import org.opencdmp.model.referencetype.ReferenceType;
|
||||||
import org.opencdmp.query.*;
|
import org.opencdmp.query.*;
|
||||||
import org.opencdmp.service.accounting.AccountingService;
|
import org.opencdmp.service.accounting.AccountingService;
|
||||||
import org.opencdmp.service.descriptiontemplate.DescriptionTemplateService;
|
import org.opencdmp.service.descriptiontemplate.DescriptionTemplateService;
|
||||||
|
import org.opencdmp.service.descriptionworkflow.DescriptionWorkflowService;
|
||||||
import org.opencdmp.service.elastic.ElasticService;
|
import org.opencdmp.service.elastic.ElasticService;
|
||||||
import org.opencdmp.service.filetransformer.FileTransformerService;
|
import org.opencdmp.service.filetransformer.FileTransformerService;
|
||||||
import org.opencdmp.service.responseutils.ResponseUtilsService;
|
import org.opencdmp.service.responseutils.ResponseUtilsService;
|
||||||
|
@ -141,6 +142,7 @@ public class DescriptionServiceImpl implements DescriptionService {
|
||||||
private final TagService tagService;
|
private final TagService tagService;
|
||||||
private final UsageLimitService usageLimitService;
|
private final UsageLimitService usageLimitService;
|
||||||
private final AccountingService accountingService;
|
private final AccountingService accountingService;
|
||||||
|
private final DescriptionWorkflowService descriptionWorkflowService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public DescriptionServiceImpl(
|
public DescriptionServiceImpl(
|
||||||
|
@ -155,7 +157,7 @@ public class DescriptionServiceImpl implements DescriptionService {
|
||||||
QueryFactory queryFactory,
|
QueryFactory queryFactory,
|
||||||
JsonHandlingService jsonHandlingService,
|
JsonHandlingService jsonHandlingService,
|
||||||
UserScope userScope,
|
UserScope userScope,
|
||||||
XmlHandlingService xmlHandlingService, NotifyIntegrationEventHandler eventHandler, NotificationProperties notificationProperties, FileTransformerService fileTransformerService, ElasticService elasticService, ValidatorFactory validatorFactory, StorageFileProperties storageFileConfig, StorageFileService storageFileService, AuthorizationContentResolver authorizationContentResolver, AnnotationEntityTouchedIntegrationEventHandler annotationEntityTouchedIntegrationEventHandler, AnnotationEntityRemovalIntegrationEventHandler annotationEntityRemovalIntegrationEventHandler, TenantScope tenantScope, ResponseUtilsService responseUtilsService, DescriptionTemplateService descriptionTemplateService, TagService tagService, UsageLimitService usageLimitService, AccountingService accountingService) {
|
XmlHandlingService xmlHandlingService, NotifyIntegrationEventHandler eventHandler, NotificationProperties notificationProperties, FileTransformerService fileTransformerService, ElasticService elasticService, ValidatorFactory validatorFactory, StorageFileProperties storageFileConfig, StorageFileService storageFileService, AuthorizationContentResolver authorizationContentResolver, AnnotationEntityTouchedIntegrationEventHandler annotationEntityTouchedIntegrationEventHandler, AnnotationEntityRemovalIntegrationEventHandler annotationEntityRemovalIntegrationEventHandler, TenantScope tenantScope, ResponseUtilsService responseUtilsService, DescriptionTemplateService descriptionTemplateService, TagService tagService, UsageLimitService usageLimitService, AccountingService accountingService, DescriptionWorkflowService descriptionWorkflowService) {
|
||||||
this.entityManager = entityManager;
|
this.entityManager = entityManager;
|
||||||
this.authorizationService = authorizationService;
|
this.authorizationService = authorizationService;
|
||||||
this.deleterFactory = deleterFactory;
|
this.deleterFactory = deleterFactory;
|
||||||
|
@ -184,6 +186,7 @@ public class DescriptionServiceImpl implements DescriptionService {
|
||||||
this.tagService = tagService;
|
this.tagService = tagService;
|
||||||
this.usageLimitService = usageLimitService;
|
this.usageLimitService = usageLimitService;
|
||||||
this.accountingService = accountingService;
|
this.accountingService = accountingService;
|
||||||
|
this.descriptionWorkflowService = descriptionWorkflowService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -223,9 +226,17 @@ public class DescriptionServiceImpl implements DescriptionService {
|
||||||
data = this.entityManager.find(DescriptionEntity.class, model.getId());
|
data = this.entityManager.find(DescriptionEntity.class, model.getId());
|
||||||
if (data == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), Description.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
if (data == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), Description.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.getStatus().equals(DescriptionStatus.Finalized)) throw new MyValidationException(this.errors.getDescriptionIsFinalized().getCode(), this.errors.getDescriptionIsFinalized().getMessage());
|
DescriptionStatusEntity oldDescriptionStatusEntity = this.entityManager.find(DescriptionStatusEntity.class, data.getStatusId(), true);
|
||||||
|
if (oldDescriptionStatusEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{data.getStatusId(), org.opencdmp.model.descriptionstatus.DescriptionStatus.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||||
|
if (oldDescriptionStatusEntity.getInternalStatus() != null && oldDescriptionStatusEntity.getInternalStatus().equals(DescriptionStatus.Finalized)) throw new MyValidationException(this.errors.getDescriptionIsFinalized().getCode(), this.errors.getDescriptionIsFinalized().getMessage());
|
||||||
if (!data.getPlanId().equals(model.getPlanId())) throw new MyValidationException(this.errors.getPlanCanNotChange().getCode(), this.errors.getPlanCanNotChange().getMessage());
|
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());
|
if (!data.getPlanDescriptionTemplateId().equals(model.getPlanDescriptionTemplateId())) throw new MyValidationException(this.errors.getPlanDescriptionTemplateCanNotChange().getCode(), this.errors.getPlanDescriptionTemplateCanNotChange().getMessage());
|
||||||
|
if (model.getStatusId() != null && !model.getStatusId().equals(data.getStatusId())) {
|
||||||
|
data.setStatusId(model.getStatusId());
|
||||||
|
DescriptionStatusEntity newDescriptionStatusEntity = this.entityManager.find(DescriptionStatusEntity.class, model.getStatusId(), true);
|
||||||
|
if (newDescriptionStatusEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{model.getStatusId(), org.opencdmp.model.descriptionstatus.DescriptionStatus.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||||
|
if (newDescriptionStatusEntity.getInternalStatus() != null && newDescriptionStatusEntity.getInternalStatus().equals(DescriptionStatus.Finalized)) data.setFinalizedAt(Instant.now());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.usageLimitService.checkIncrease(UsageLimitTargetMetric.DESCRIPTION_COUNT);
|
this.usageLimitService.checkIncrease(UsageLimitTargetMetric.DESCRIPTION_COUNT);
|
||||||
|
|
||||||
|
@ -244,6 +255,8 @@ public class DescriptionServiceImpl implements DescriptionService {
|
||||||
data.setCreatedById(this.userScope.getUserId());
|
data.setCreatedById(this.userScope.getUserId());
|
||||||
data.setPlanId(model.getPlanId());
|
data.setPlanId(model.getPlanId());
|
||||||
data.setPlanDescriptionTemplateId(model.getPlanDescriptionTemplateId());
|
data.setPlanDescriptionTemplateId(model.getPlanDescriptionTemplateId());
|
||||||
|
data.setStatus(DescriptionStatus.Draft);
|
||||||
|
data.setStatusId(this.descriptionWorkflowService.getWorkFlowDefinition().getStartingStatusId());
|
||||||
}
|
}
|
||||||
|
|
||||||
DescriptionTemplateEntity descriptionTemplateEntity = this.entityManager.find(DescriptionTemplateEntity.class, model.getDescriptionTemplateId(), true);
|
DescriptionTemplateEntity descriptionTemplateEntity = this.entityManager.find(DescriptionTemplateEntity.class, model.getDescriptionTemplateId(), true);
|
||||||
|
@ -257,8 +270,6 @@ public class DescriptionServiceImpl implements DescriptionService {
|
||||||
if (plan.getStatus().equals(PlanStatus.Finalized) && isUpdate) throw new MyValidationException(this.errors.getPlanIsFinalized().getCode(), this.errors.getPlanIsFinalized().getMessage());
|
if (plan.getStatus().equals(PlanStatus.Finalized) && isUpdate) throw new MyValidationException(this.errors.getPlanIsFinalized().getCode(), this.errors.getPlanIsFinalized().getMessage());
|
||||||
|
|
||||||
data.setLabel(model.getLabel());
|
data.setLabel(model.getLabel());
|
||||||
data.setStatus(model.getStatus());
|
|
||||||
if (model.getStatus() == DescriptionStatus.Finalized) data.setFinalizedAt(Instant.now());
|
|
||||||
data.setDescription(model.getDescription());
|
data.setDescription(model.getDescription());
|
||||||
data.setDescriptionTemplateId(model.getDescriptionTemplateId());
|
data.setDescriptionTemplateId(model.getDescriptionTemplateId());
|
||||||
data.setUpdatedAt(Instant.now());
|
data.setUpdatedAt(Instant.now());
|
||||||
|
@ -376,6 +387,10 @@ public class DescriptionServiceImpl implements DescriptionService {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendNotification(DescriptionEntity description, Boolean isUpdate) throws InvalidApplicationException {
|
private void sendNotification(DescriptionEntity description, Boolean isUpdate) throws InvalidApplicationException {
|
||||||
|
DescriptionStatusEntity descriptionStatusEntity = this.entityManager.find(DescriptionStatusEntity.class, description.getStatusId(), true);
|
||||||
|
if (descriptionStatusEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{description, DescriptionStatus.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||||
|
if (descriptionStatusEntity.getInternalStatus() == null || descriptionStatusEntity.getInternalStatus().equals(DescriptionStatus.Canceled)) return;
|
||||||
|
|
||||||
List<PlanUserEntity> existingUsers = this.queryFactory.query(PlanUserQuery.class).disableTracking()
|
List<PlanUserEntity> existingUsers = this.queryFactory.query(PlanUserQuery.class).disableTracking()
|
||||||
.planIds(description.getPlanId())
|
.planIds(description.getPlanId())
|
||||||
.isActives(IsActive.Active)
|
.isActives(IsActive.Active)
|
||||||
|
@ -388,7 +403,7 @@ public class DescriptionServiceImpl implements DescriptionService {
|
||||||
if (!planUser.getUserId().equals(this.userScope.getUserIdSafe())){
|
if (!planUser.getUserId().equals(this.userScope.getUserIdSafe())){
|
||||||
UserEntity user = this.queryFactory.query(UserQuery.class).disableTracking().ids(planUser.getUserId()).first();
|
UserEntity user = this.queryFactory.query(UserQuery.class).disableTracking().ids(planUser.getUserId()).first();
|
||||||
if (user == null || user.getIsActive().equals(IsActive.Inactive)) throw new MyValidationException(this.errors.getPlanInactiveUser().getCode(), this.errors.getPlanInactiveUser().getMessage());
|
if (user == null || user.getIsActive().equals(IsActive.Inactive)) throw new MyValidationException(this.errors.getPlanInactiveUser().getCode(), this.errors.getPlanInactiveUser().getMessage());
|
||||||
this.createDescriptionNotificationEvent(description, user, isUpdate);
|
this.createDescriptionNotificationEvent(description, descriptionStatusEntity.getInternalStatus(), user, isUpdate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -437,11 +452,11 @@ public class DescriptionServiceImpl implements DescriptionService {
|
||||||
return cleanData;
|
return cleanData;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createDescriptionNotificationEvent(DescriptionEntity description, UserEntity user, Boolean isUpdate) throws InvalidApplicationException {
|
private void createDescriptionNotificationEvent(DescriptionEntity description, DescriptionStatus internalStatus, UserEntity user, Boolean isUpdate) throws InvalidApplicationException {
|
||||||
NotifyIntegrationEvent event = new NotifyIntegrationEvent();
|
NotifyIntegrationEvent event = new NotifyIntegrationEvent();
|
||||||
event.setUserId(user.getId());
|
event.setUserId(user.getId());
|
||||||
|
|
||||||
this.applyNotificationType(description.getStatus(), event, isUpdate);
|
this.applyNotificationType(internalStatus, event, isUpdate);
|
||||||
NotificationFieldData data = new NotificationFieldData();
|
NotificationFieldData data = new NotificationFieldData();
|
||||||
List<FieldInfo> fieldInfoList = new ArrayList<>();
|
List<FieldInfo> fieldInfoList = new ArrayList<>();
|
||||||
fieldInfoList.add(new FieldInfo("{recipient}", DataType.String, user.getName()));
|
fieldInfoList.add(new FieldInfo("{recipient}", DataType.String, user.getName()));
|
||||||
|
@ -482,16 +497,20 @@ public class DescriptionServiceImpl implements DescriptionService {
|
||||||
DescriptionEntity data = this.entityManager.find(DescriptionEntity.class, model.getId());
|
DescriptionEntity data = this.entityManager.find(DescriptionEntity.class, model.getId());
|
||||||
if (data == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), Description.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
if (data == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), Description.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.getStatus().equals(model.getStatus())){
|
if (!data.getStatusId().equals(model.getStatusId())){
|
||||||
if (data.getStatus().equals(DescriptionStatus.Finalized)){
|
DescriptionStatusEntity oldStatusEntity = this.queryFactory.query(DescriptionStatusQuery.class).disableTracking().ids(data.getStatusId()).isActive(IsActive.Active).firstAs(new BaseFieldSet().ensure(org.opencdmp.model.descriptionstatus.DescriptionStatus._id).ensure(org.opencdmp.model.descriptionstatus.DescriptionStatus._internalStatus));
|
||||||
|
if (oldStatusEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{data.getStatusId(), DescriptionStatusEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||||
|
if (oldStatusEntity.getInternalStatus() != null && oldStatusEntity.getInternalStatus().equals(DescriptionStatus.Finalized)){
|
||||||
this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.descriptionAffiliation(model.getId())), Permission.FinalizeDescription);
|
this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.descriptionAffiliation(model.getId())), Permission.FinalizeDescription);
|
||||||
PlanEntity planEntity = this.entityManager.find(PlanEntity.class, data.getPlanId(), true);
|
PlanEntity planEntity = this.entityManager.find(PlanEntity.class, data.getPlanId(), true);
|
||||||
if (planEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{data.getPlanId(), PlanEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
if (planEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{data.getPlanId(), PlanEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||||
if(!planEntity.getStatus().equals(PlanStatus.Draft)) throw new MyValidationException(this.errors.getPlanIsFinalized().getCode(), this.errors.getPlanIsFinalized().getMessage());
|
if(!planEntity.getStatus().equals(PlanStatus.Draft)) throw new MyValidationException(this.errors.getPlanIsFinalized().getCode(), this.errors.getPlanIsFinalized().getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
data.setStatus(model.getStatus());
|
data.setStatusId(model.getStatusId());
|
||||||
if (model.getStatus() == DescriptionStatus.Finalized) data.setFinalizedAt(Instant.now());
|
DescriptionStatusEntity newStatusEntity = this.queryFactory.query(DescriptionStatusQuery.class).disableTracking().ids(model.getStatusId()).isActive(IsActive.Active).firstAs(new BaseFieldSet().ensure(org.opencdmp.model.descriptionstatus.DescriptionStatus._id).ensure(org.opencdmp.model.descriptionstatus.DescriptionStatus._internalStatus));
|
||||||
|
if (newStatusEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{model.getStatusId(), DescriptionStatusEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||||
|
if (newStatusEntity.getInternalStatus() != null && newStatusEntity.getInternalStatus().equals(DescriptionStatus.Finalized)) data.setFinalizedAt(Instant.now());
|
||||||
data.setUpdatedAt(Instant.now());
|
data.setUpdatedAt(Instant.now());
|
||||||
this.entityManager.merge(data);
|
this.entityManager.merge(data);
|
||||||
|
|
||||||
|
@ -501,7 +520,7 @@ public class DescriptionServiceImpl implements DescriptionService {
|
||||||
this.eventBroker.emit(new DescriptionTouchedEvent(data.getId()));
|
this.eventBroker.emit(new DescriptionTouchedEvent(data.getId()));
|
||||||
|
|
||||||
this.annotationEntityTouchedIntegrationEventHandler.handleDescription(data.getId());
|
this.annotationEntityTouchedIntegrationEventHandler.handleDescription(data.getId());
|
||||||
if (data.getStatus().equals(DescriptionStatus.Finalized)) this.sendNotification(data, true);
|
if (newStatusEntity.getInternalStatus() != null && newStatusEntity.getInternalStatus().equals(DescriptionStatus.Finalized)) this.sendNotification(data, true);
|
||||||
}
|
}
|
||||||
return this.builderFactory.builder(DescriptionBuilder.class).authorize(AuthorizationFlags.AllExceptPublic).build(BaseFieldSet.build(fields, Description._id), data);
|
return this.builderFactory.builder(DescriptionBuilder.class).authorize(AuthorizationFlags.AllExceptPublic).build(BaseFieldSet.build(fields, Description._id), data);
|
||||||
}
|
}
|
||||||
|
@ -1003,7 +1022,8 @@ public class DescriptionServiceImpl implements DescriptionService {
|
||||||
|
|
||||||
persist.setId(data.getId());
|
persist.setId(data.getId());
|
||||||
persist.setLabel(data.getLabel());
|
persist.setLabel(data.getLabel());
|
||||||
persist.setStatus(DescriptionStatus.Finalized);
|
DescriptionStatusEntity statusEntity = this.queryFactory.query(DescriptionStatusQuery.class).disableTracking().internalStatuses(DescriptionStatus.Finalized).isActive(IsActive.Active).firstAs(new BaseFieldSet().ensure(org.opencdmp.model.descriptionstatus.DescriptionStatus._id));
|
||||||
|
if (statusEntity != null) persist.setStatusId(statusEntity.getId());
|
||||||
persist.setDescription(data.getDescription());
|
persist.setDescription(data.getDescription());
|
||||||
persist.setDescriptionTemplateId(data.getDescriptionTemplateId());
|
persist.setDescriptionTemplateId(data.getDescriptionTemplateId());
|
||||||
persist.setPlanId(data.getPlanId());
|
persist.setPlanId(data.getPlanId());
|
||||||
|
@ -1382,7 +1402,8 @@ public class DescriptionServiceImpl implements DescriptionService {
|
||||||
DescriptionPersist persist = new DescriptionPersist();
|
DescriptionPersist persist = new DescriptionPersist();
|
||||||
persist.setLabel(descriptionXml.getLabel());
|
persist.setLabel(descriptionXml.getLabel());
|
||||||
persist.setDescription(descriptionXml.getDescription());
|
persist.setDescription(descriptionXml.getDescription());
|
||||||
persist.setStatus(DescriptionStatus.Draft);
|
DescriptionStatusEntity statusEntity = this.queryFactory.query(DescriptionStatusQuery.class).disableTracking().isActive(IsActive.Active).internalStatuses(DescriptionStatus.Draft).firstAs(new BaseFieldSet().ensure(org.opencdmp.model.descriptionstatus.DescriptionStatus._id));
|
||||||
|
if (statusEntity != null) persist.setStatusId(statusEntity.getId());
|
||||||
persist.setPlanId(planId);
|
persist.setPlanId(planId);
|
||||||
persist.setDescriptionTemplateId(this.xmlToDescriptionTemplatePersist(descriptionXml));
|
persist.setDescriptionTemplateId(this.xmlToDescriptionTemplatePersist(descriptionXml));
|
||||||
persist.setPlanDescriptionTemplateId(this.xmlToPlanDescriptionTemplatePersist(descriptionXml, planId));
|
persist.setPlanDescriptionTemplateId(this.xmlToPlanDescriptionTemplatePersist(descriptionXml, planId));
|
||||||
|
@ -1598,7 +1619,8 @@ public class DescriptionServiceImpl implements DescriptionService {
|
||||||
DescriptionPersist persist = new DescriptionPersist();
|
DescriptionPersist persist = new DescriptionPersist();
|
||||||
persist.setLabel(model.getLabel());
|
persist.setLabel(model.getLabel());
|
||||||
persist.setDescription(model.getDescription());
|
persist.setDescription(model.getDescription());
|
||||||
persist.setStatus(DescriptionStatus.Draft);
|
DescriptionStatusEntity statusEntity = this.queryFactory.query(DescriptionStatusQuery.class).disableTracking().isActive(IsActive.Active).internalStatuses(DescriptionStatus.Draft).firstAs(new BaseFieldSet().ensure(org.opencdmp.model.descriptionstatus.DescriptionStatus._id));
|
||||||
|
if (statusEntity != null) persist.setStatusId(statusEntity.getId());
|
||||||
persist.setPlanId(planId);
|
persist.setPlanId(planId);
|
||||||
persist.setDescriptionTemplateId(this.commonModelToDescriptionTemplatePersist(model));
|
persist.setDescriptionTemplateId(this.commonModelToDescriptionTemplatePersist(model));
|
||||||
persist.setPlanDescriptionTemplateId(this.commonModelTToPlanDescriptionTemplatePersist(model, planId));
|
persist.setPlanDescriptionTemplateId(this.commonModelTToPlanDescriptionTemplatePersist(model, planId));
|
||||||
|
|
|
@ -10,6 +10,7 @@ import org.opencdmp.model.descriptionstatus.DescriptionStatus;
|
||||||
import org.opencdmp.model.persist.descriptionstatus.DescriptionStatusPersist;
|
import org.opencdmp.model.persist.descriptionstatus.DescriptionStatusPersist;
|
||||||
|
|
||||||
import javax.management.InvalidApplicationException;
|
import javax.management.InvalidApplicationException;
|
||||||
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public interface DescriptionStatusService {
|
public interface DescriptionStatusService {
|
||||||
|
@ -17,4 +18,6 @@ public interface DescriptionStatusService {
|
||||||
DescriptionStatus persist(DescriptionStatusPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JAXBException;
|
DescriptionStatus persist(DescriptionStatusPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JAXBException;
|
||||||
|
|
||||||
void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException;
|
void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException;
|
||||||
|
|
||||||
|
List<DescriptionStatus> getAvailableTransitionStatuses(UUID descriptionId) throws InvalidApplicationException;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package org.opencdmp.service.descriptionstatus;
|
||||||
import gr.cite.commons.web.authz.service.AuthorizationService;
|
import gr.cite.commons.web.authz.service.AuthorizationService;
|
||||||
import gr.cite.tools.data.builder.BuilderFactory;
|
import gr.cite.tools.data.builder.BuilderFactory;
|
||||||
import gr.cite.tools.data.deleter.DeleterFactory;
|
import gr.cite.tools.data.deleter.DeleterFactory;
|
||||||
|
import gr.cite.tools.data.query.QueryFactory;
|
||||||
import gr.cite.tools.exception.MyApplicationException;
|
import gr.cite.tools.exception.MyApplicationException;
|
||||||
import gr.cite.tools.exception.MyForbiddenException;
|
import gr.cite.tools.exception.MyForbiddenException;
|
||||||
import gr.cite.tools.exception.MyNotFoundException;
|
import gr.cite.tools.exception.MyNotFoundException;
|
||||||
|
@ -12,22 +13,29 @@ import gr.cite.tools.fieldset.FieldSet;
|
||||||
import gr.cite.tools.logging.LoggerService;
|
import gr.cite.tools.logging.LoggerService;
|
||||||
import gr.cite.tools.logging.MapLogEntry;
|
import gr.cite.tools.logging.MapLogEntry;
|
||||||
import jakarta.xml.bind.JAXBException;
|
import jakarta.xml.bind.JAXBException;
|
||||||
|
import org.opencdmp.authorization.AuthorizationFlags;
|
||||||
import org.opencdmp.authorization.Permission;
|
import org.opencdmp.authorization.Permission;
|
||||||
import org.opencdmp.commons.XmlHandlingService;
|
import org.opencdmp.commons.XmlHandlingService;
|
||||||
import org.opencdmp.commons.enums.IsActive;
|
import org.opencdmp.commons.enums.IsActive;
|
||||||
import org.opencdmp.commons.types.descriptionstatus.DescriptionStatusDefinitionAuthorizationEntity;
|
import org.opencdmp.commons.types.descriptionstatus.DescriptionStatusDefinitionAuthorizationEntity;
|
||||||
import org.opencdmp.commons.types.descriptionstatus.DescriptionStatusDefinitionAuthorizationItemEntity;
|
import org.opencdmp.commons.types.descriptionstatus.DescriptionStatusDefinitionAuthorizationItemEntity;
|
||||||
import org.opencdmp.commons.types.descriptionstatus.DescriptionStatusDefinitionEntity;
|
import org.opencdmp.commons.types.descriptionstatus.DescriptionStatusDefinitionEntity;
|
||||||
|
import org.opencdmp.commons.types.descriptionworkflow.DescriptionWorkflowDefinitionEntity;
|
||||||
|
import org.opencdmp.commons.types.descriptionworkflow.DescriptionWorkflowDefinitionTransitionEntity;
|
||||||
import org.opencdmp.convention.ConventionService;
|
import org.opencdmp.convention.ConventionService;
|
||||||
|
import org.opencdmp.data.DescriptionEntity;
|
||||||
import org.opencdmp.data.DescriptionStatusEntity;
|
import org.opencdmp.data.DescriptionStatusEntity;
|
||||||
import org.opencdmp.data.TenantEntityManager;
|
import org.opencdmp.data.TenantEntityManager;
|
||||||
import org.opencdmp.model.builder.descriptionstatus.DescriptionStatusBuilder;
|
import org.opencdmp.model.builder.descriptionstatus.DescriptionStatusBuilder;
|
||||||
import org.opencdmp.model.deleter.DescriptionStatusDeleter;
|
import org.opencdmp.model.deleter.DescriptionStatusDeleter;
|
||||||
|
import org.opencdmp.model.description.Description;
|
||||||
import org.opencdmp.model.descriptionstatus.DescriptionStatus;
|
import org.opencdmp.model.descriptionstatus.DescriptionStatus;
|
||||||
import org.opencdmp.model.persist.descriptionstatus.DescriptionStatusDefinitionAuthorizationItemPersist;
|
import org.opencdmp.model.persist.descriptionstatus.DescriptionStatusDefinitionAuthorizationItemPersist;
|
||||||
import org.opencdmp.model.persist.descriptionstatus.DescriptionStatusDefinitionAuthorizationPersist;
|
import org.opencdmp.model.persist.descriptionstatus.DescriptionStatusDefinitionAuthorizationPersist;
|
||||||
import org.opencdmp.model.persist.descriptionstatus.DescriptionStatusDefinitionPersist;
|
import org.opencdmp.model.persist.descriptionstatus.DescriptionStatusDefinitionPersist;
|
||||||
import org.opencdmp.model.persist.descriptionstatus.DescriptionStatusPersist;
|
import org.opencdmp.model.persist.descriptionstatus.DescriptionStatusPersist;
|
||||||
|
import org.opencdmp.query.DescriptionStatusQuery;
|
||||||
|
import org.opencdmp.service.descriptionworkflow.DescriptionWorkflowService;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.context.MessageSource;
|
import org.springframework.context.MessageSource;
|
||||||
import org.springframework.context.i18n.LocaleContextHolder;
|
import org.springframework.context.i18n.LocaleContextHolder;
|
||||||
|
@ -35,8 +43,10 @@ import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.management.InvalidApplicationException;
|
import javax.management.InvalidApplicationException;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class DescriptionStatusServiceImpl implements DescriptionStatusService {
|
public class DescriptionStatusServiceImpl implements DescriptionStatusService {
|
||||||
|
@ -51,8 +61,10 @@ public class DescriptionStatusServiceImpl implements DescriptionStatusService {
|
||||||
private final ConventionService conventionService;
|
private final ConventionService conventionService;
|
||||||
private final MessageSource messageSource;
|
private final MessageSource messageSource;
|
||||||
private final XmlHandlingService xmlHandlingService;
|
private final XmlHandlingService xmlHandlingService;
|
||||||
|
private final QueryFactory queryFactory;
|
||||||
|
private final DescriptionWorkflowService descriptionWorkflowService;
|
||||||
|
|
||||||
public DescriptionStatusServiceImpl(BuilderFactory builderFactory, DeleterFactory deleterFactory, AuthorizationService authService, TenantEntityManager entityManager, ConventionService conventionService, MessageSource messageSource, XmlHandlingService xmlHandlingService) {
|
public DescriptionStatusServiceImpl(BuilderFactory builderFactory, DeleterFactory deleterFactory, AuthorizationService authService, TenantEntityManager entityManager, ConventionService conventionService, MessageSource messageSource, XmlHandlingService xmlHandlingService, QueryFactory queryFactory, DescriptionWorkflowService descriptionWorkflowService) {
|
||||||
this.builderFactory = builderFactory;
|
this.builderFactory = builderFactory;
|
||||||
this.deleterFactory = deleterFactory;
|
this.deleterFactory = deleterFactory;
|
||||||
|
|
||||||
|
@ -61,6 +73,8 @@ public class DescriptionStatusServiceImpl implements DescriptionStatusService {
|
||||||
this.conventionService = conventionService;
|
this.conventionService = conventionService;
|
||||||
this.messageSource = messageSource;
|
this.messageSource = messageSource;
|
||||||
this.xmlHandlingService = xmlHandlingService;
|
this.xmlHandlingService = xmlHandlingService;
|
||||||
|
this.queryFactory = queryFactory;
|
||||||
|
this.descriptionWorkflowService = descriptionWorkflowService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -141,4 +155,20 @@ public class DescriptionStatusServiceImpl implements DescriptionStatusService {
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<DescriptionStatus> getAvailableTransitionStatuses(UUID descriptionId) throws InvalidApplicationException {
|
||||||
|
DescriptionWorkflowDefinitionEntity definition = this.descriptionWorkflowService.getWorkFlowDefinition();
|
||||||
|
|
||||||
|
DescriptionEntity description = this.entityManager.find(DescriptionEntity.class, descriptionId);
|
||||||
|
if (description == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{descriptionId, Description.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||||
|
|
||||||
|
List<DescriptionWorkflowDefinitionTransitionEntity> availableTransitions = definition.getStatusTransitions().stream().filter(x -> x.getFromStatusId().equals(description.getStatusId())).collect(Collectors.toList());
|
||||||
|
if (!this.conventionService.isListNullOrEmpty(availableTransitions)){
|
||||||
|
DescriptionStatusQuery query = this.queryFactory.query(DescriptionStatusQuery.class).authorize(AuthorizationFlags.AllExceptPublic).isActive(IsActive.Active).ids(availableTransitions.stream().map(DescriptionWorkflowDefinitionTransitionEntity::getToStatusId).distinct().toList());
|
||||||
|
FieldSet fieldSet = new BaseFieldSet().ensure(DescriptionStatus._id).ensure(DescriptionStatus._name).ensure(DescriptionStatus._internalStatus);
|
||||||
|
return this.builderFactory.builder(DescriptionStatusBuilder.class).authorize(AuthorizationFlags.AllExceptPublic).build(fieldSet, query.collectAs(fieldSet));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package org.opencdmp.service.descriptionworkflow;
|
package org.opencdmp.service.descriptionworkflow;
|
||||||
|
|
||||||
import gr.cite.tools.fieldset.FieldSet;
|
import gr.cite.tools.fieldset.FieldSet;
|
||||||
|
import org.opencdmp.commons.types.descriptionworkflow.DescriptionWorkflowDefinitionEntity;
|
||||||
import org.opencdmp.model.descriptionworkflow.DescriptionWorkflow;
|
import org.opencdmp.model.descriptionworkflow.DescriptionWorkflow;
|
||||||
import org.opencdmp.model.persist.descriptionworkflow.DescriptionWorkflowPersist;
|
import org.opencdmp.model.persist.descriptionworkflow.DescriptionWorkflowPersist;
|
||||||
|
|
||||||
|
@ -11,4 +12,6 @@ public interface DescriptionWorkflowService {
|
||||||
DescriptionWorkflow persist(DescriptionWorkflowPersist persist, FieldSet fields) throws InvalidApplicationException;
|
DescriptionWorkflow persist(DescriptionWorkflowPersist persist, FieldSet fields) throws InvalidApplicationException;
|
||||||
|
|
||||||
void deleteAndSave(UUID id) throws InvalidApplicationException;
|
void deleteAndSave(UUID id) throws InvalidApplicationException;
|
||||||
|
|
||||||
|
DescriptionWorkflowDefinitionEntity getWorkFlowDefinition() throws InvalidApplicationException;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,15 +3,19 @@ package org.opencdmp.service.descriptionworkflow;
|
||||||
import gr.cite.commons.web.authz.service.AuthorizationService;
|
import gr.cite.commons.web.authz.service.AuthorizationService;
|
||||||
import gr.cite.tools.data.builder.BuilderFactory;
|
import gr.cite.tools.data.builder.BuilderFactory;
|
||||||
import gr.cite.tools.data.deleter.DeleterFactory;
|
import gr.cite.tools.data.deleter.DeleterFactory;
|
||||||
|
import gr.cite.tools.data.query.QueryFactory;
|
||||||
|
import gr.cite.tools.exception.MyApplicationException;
|
||||||
import gr.cite.tools.exception.MyNotFoundException;
|
import gr.cite.tools.exception.MyNotFoundException;
|
||||||
import gr.cite.tools.exception.MyValidationException;
|
import gr.cite.tools.exception.MyValidationException;
|
||||||
import gr.cite.tools.fieldset.BaseFieldSet;
|
import gr.cite.tools.fieldset.BaseFieldSet;
|
||||||
import gr.cite.tools.fieldset.FieldSet;
|
import gr.cite.tools.fieldset.FieldSet;
|
||||||
import gr.cite.tools.logging.LoggerService;
|
import gr.cite.tools.logging.LoggerService;
|
||||||
import gr.cite.tools.logging.MapLogEntry;
|
import gr.cite.tools.logging.MapLogEntry;
|
||||||
|
import org.opencdmp.authorization.AuthorizationFlags;
|
||||||
import org.opencdmp.authorization.Permission;
|
import org.opencdmp.authorization.Permission;
|
||||||
import org.opencdmp.commons.XmlHandlingService;
|
import org.opencdmp.commons.XmlHandlingService;
|
||||||
import org.opencdmp.commons.enums.IsActive;
|
import org.opencdmp.commons.enums.IsActive;
|
||||||
|
import org.opencdmp.commons.scope.tenant.TenantScope;
|
||||||
import org.opencdmp.commons.types.descriptionworkflow.DescriptionWorkflowDefinitionEntity;
|
import org.opencdmp.commons.types.descriptionworkflow.DescriptionWorkflowDefinitionEntity;
|
||||||
import org.opencdmp.commons.types.descriptionworkflow.DescriptionWorkflowDefinitionTransitionEntity;
|
import org.opencdmp.commons.types.descriptionworkflow.DescriptionWorkflowDefinitionTransitionEntity;
|
||||||
import org.opencdmp.convention.ConventionService;
|
import org.opencdmp.convention.ConventionService;
|
||||||
|
@ -24,6 +28,7 @@ import org.opencdmp.model.descriptionworkflow.DescriptionWorkflow;
|
||||||
import org.opencdmp.model.persist.descriptionworkflow.DescriptionWorkflowDefinitionPersist;
|
import org.opencdmp.model.persist.descriptionworkflow.DescriptionWorkflowDefinitionPersist;
|
||||||
import org.opencdmp.model.persist.descriptionworkflow.DescriptionWorkflowDefinitionTransitionPersist;
|
import org.opencdmp.model.persist.descriptionworkflow.DescriptionWorkflowDefinitionTransitionPersist;
|
||||||
import org.opencdmp.model.persist.descriptionworkflow.DescriptionWorkflowPersist;
|
import org.opencdmp.model.persist.descriptionworkflow.DescriptionWorkflowPersist;
|
||||||
|
import org.opencdmp.query.DescriptionWorkflowQuery;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.context.MessageSource;
|
import org.springframework.context.MessageSource;
|
||||||
import org.springframework.context.i18n.LocaleContextHolder;
|
import org.springframework.context.i18n.LocaleContextHolder;
|
||||||
|
@ -48,8 +53,10 @@ public class DescriptionWorkflowServiceImpl implements DescriptionWorkflowServic
|
||||||
private final TenantEntityManager entityManager;
|
private final TenantEntityManager entityManager;
|
||||||
private final MessageSource messageSource;
|
private final MessageSource messageSource;
|
||||||
private final ErrorThesaurusProperties errors;
|
private final ErrorThesaurusProperties errors;
|
||||||
|
private final TenantScope tenantScope;
|
||||||
|
private final QueryFactory queryFactory;
|
||||||
|
|
||||||
public DescriptionWorkflowServiceImpl(AuthorizationService authService, ConventionService conventionService, XmlHandlingService xmlHandlingService, BuilderFactory builderFactory, DeleterFactory deleterFactory, TenantEntityManager entityManager, MessageSource messageSource, ErrorThesaurusProperties errors) {
|
public DescriptionWorkflowServiceImpl(AuthorizationService authService, ConventionService conventionService, XmlHandlingService xmlHandlingService, BuilderFactory builderFactory, DeleterFactory deleterFactory, TenantEntityManager entityManager, MessageSource messageSource, ErrorThesaurusProperties errors, TenantScope tenantScope, QueryFactory queryFactory) {
|
||||||
this.authService = authService;
|
this.authService = authService;
|
||||||
this.conventionService = conventionService;
|
this.conventionService = conventionService;
|
||||||
this.xmlHandlingService = xmlHandlingService;
|
this.xmlHandlingService = xmlHandlingService;
|
||||||
|
@ -58,6 +65,8 @@ public class DescriptionWorkflowServiceImpl implements DescriptionWorkflowServic
|
||||||
this.entityManager = entityManager;
|
this.entityManager = entityManager;
|
||||||
this.messageSource = messageSource;
|
this.messageSource = messageSource;
|
||||||
this.errors = errors;
|
this.errors = errors;
|
||||||
|
this.tenantScope = tenantScope;
|
||||||
|
this.queryFactory = queryFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -132,4 +141,22 @@ public class DescriptionWorkflowServiceImpl implements DescriptionWorkflowServic
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DescriptionWorkflowDefinitionEntity getWorkFlowDefinition() throws InvalidApplicationException {
|
||||||
|
DescriptionWorkflowQuery query = this.queryFactory.query(DescriptionWorkflowQuery.class).authorize(AuthorizationFlags.AllExceptPublic).isActives(IsActive.Active);
|
||||||
|
|
||||||
|
if (this.tenantScope.isDefaultTenant())
|
||||||
|
query = query.defaultTenant(true);
|
||||||
|
else
|
||||||
|
query = query.tenantIds(this.tenantScope.getTenant());
|
||||||
|
|
||||||
|
DescriptionWorkflowEntity entity = query.first();
|
||||||
|
if (entity == null) throw new MyApplicationException("Description workflow not found!");
|
||||||
|
|
||||||
|
DescriptionWorkflowDefinitionEntity definition = this.xmlHandlingService.fromXmlSafe(DescriptionWorkflowDefinitionEntity.class, entity.getDefinition());
|
||||||
|
if (definition == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{entity.getId(), DescriptionWorkflowDefinitionEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||||
|
|
||||||
|
return definition;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,6 +98,7 @@ import org.opencdmp.service.accounting.AccountingService;
|
||||||
import org.opencdmp.service.actionconfirmation.ActionConfirmationService;
|
import org.opencdmp.service.actionconfirmation.ActionConfirmationService;
|
||||||
import org.opencdmp.service.description.DescriptionService;
|
import org.opencdmp.service.description.DescriptionService;
|
||||||
import org.opencdmp.service.descriptiontemplate.DescriptionTemplateService;
|
import org.opencdmp.service.descriptiontemplate.DescriptionTemplateService;
|
||||||
|
import org.opencdmp.service.descriptionworkflow.DescriptionWorkflowService;
|
||||||
import org.opencdmp.service.elastic.ElasticService;
|
import org.opencdmp.service.elastic.ElasticService;
|
||||||
import org.opencdmp.service.filetransformer.FileTransformerService;
|
import org.opencdmp.service.filetransformer.FileTransformerService;
|
||||||
import org.opencdmp.service.planblueprint.PlanBlueprintService;
|
import org.opencdmp.service.planblueprint.PlanBlueprintService;
|
||||||
|
@ -183,6 +184,7 @@ public class PlanServiceImpl implements PlanService {
|
||||||
private final PlanBlueprintService planBlueprintService;
|
private final PlanBlueprintService planBlueprintService;
|
||||||
private final UsageLimitService usageLimitService;
|
private final UsageLimitService usageLimitService;
|
||||||
private final AccountingService accountingService;
|
private final AccountingService accountingService;
|
||||||
|
private final DescriptionWorkflowService descriptionWorkflowService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public PlanServiceImpl(
|
public PlanServiceImpl(
|
||||||
|
@ -205,7 +207,7 @@ public class PlanServiceImpl implements PlanService {
|
||||||
FileTransformerService fileTransformerService,
|
FileTransformerService fileTransformerService,
|
||||||
ValidatorFactory validatorFactory,
|
ValidatorFactory validatorFactory,
|
||||||
ElasticService elasticService, DescriptionTemplateService descriptionTemplateService,
|
ElasticService elasticService, DescriptionTemplateService descriptionTemplateService,
|
||||||
AnnotationEntityTouchedIntegrationEventHandler annotationEntityTouchedIntegrationEventHandler, AnnotationEntityRemovalIntegrationEventHandler annotationEntityRemovalIntegrationEventHandler, AuthorizationContentResolver authorizationContentResolver, TenantScope tenantScope, ResponseUtilsService responseUtilsService, PlanBlueprintService planBlueprintService, UsageLimitService usageLimitService, AccountingService accountingService) {
|
AnnotationEntityTouchedIntegrationEventHandler annotationEntityTouchedIntegrationEventHandler, AnnotationEntityRemovalIntegrationEventHandler annotationEntityRemovalIntegrationEventHandler, AuthorizationContentResolver authorizationContentResolver, TenantScope tenantScope, ResponseUtilsService responseUtilsService, PlanBlueprintService planBlueprintService, UsageLimitService usageLimitService, AccountingService accountingService, DescriptionWorkflowService descriptionWorkflowService) {
|
||||||
this.entityManager = entityManager;
|
this.entityManager = entityManager;
|
||||||
this.authorizationService = authorizationService;
|
this.authorizationService = authorizationService;
|
||||||
this.deleterFactory = deleterFactory;
|
this.deleterFactory = deleterFactory;
|
||||||
|
@ -234,6 +236,7 @@ public class PlanServiceImpl implements PlanService {
|
||||||
this.planBlueprintService = planBlueprintService;
|
this.planBlueprintService = planBlueprintService;
|
||||||
this.usageLimitService = usageLimitService;
|
this.usageLimitService = usageLimitService;
|
||||||
this.accountingService = accountingService;
|
this.accountingService = accountingService;
|
||||||
|
this.descriptionWorkflowService = descriptionWorkflowService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Plan persist(PlanPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JAXBException, IOException {
|
public Plan persist(PlanPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JAXBException, IOException {
|
||||||
|
@ -620,6 +623,7 @@ public class PlanServiceImpl implements PlanService {
|
||||||
newDescription.setLabel(existing.getLabel());
|
newDescription.setLabel(existing.getLabel());
|
||||||
newDescription.setDescription(existing.getDescription());
|
newDescription.setDescription(existing.getDescription());
|
||||||
newDescription.setStatus(DescriptionStatus.Draft);
|
newDescription.setStatus(DescriptionStatus.Draft);
|
||||||
|
newDescription.setStatusId(this.descriptionWorkflowService.getWorkFlowDefinition().getStartingStatusId());
|
||||||
newDescription.setProperties(existing.getProperties());
|
newDescription.setProperties(existing.getProperties());
|
||||||
newDescription.setPlanId(planId);
|
newDescription.setPlanId(planId);
|
||||||
if (newPlanDescriptionTemplateId == null && planDescriptionTemplateRemap != null) newDescription.setPlanDescriptionTemplateId(planDescriptionTemplateRemap.get(existing.getPlanDescriptionTemplateId()));
|
if (newPlanDescriptionTemplateId == null && planDescriptionTemplateRemap != null) newDescription.setPlanDescriptionTemplateId(planDescriptionTemplateRemap.get(existing.getPlanDescriptionTemplateId()));
|
||||||
|
@ -740,6 +744,7 @@ public class PlanServiceImpl implements PlanService {
|
||||||
newDescription.setLabel(existing.getLabel());
|
newDescription.setLabel(existing.getLabel());
|
||||||
newDescription.setDescription(existing.getDescription());
|
newDescription.setDescription(existing.getDescription());
|
||||||
newDescription.setStatus(DescriptionStatus.Draft);
|
newDescription.setStatus(DescriptionStatus.Draft);
|
||||||
|
newDescription.setStatusId(this.descriptionWorkflowService.getWorkFlowDefinition().getStartingStatusId());
|
||||||
newDescription.setProperties(existing.getProperties());
|
newDescription.setProperties(existing.getProperties());
|
||||||
newDescription.setPlanId(planId);
|
newDescription.setPlanId(planId);
|
||||||
if (planDescriptionTemplateRemap != null) newDescription.setPlanDescriptionTemplateId(planDescriptionTemplateRemap.get(existing.getPlanDescriptionTemplateId()));
|
if (planDescriptionTemplateRemap != null) newDescription.setPlanDescriptionTemplateId(planDescriptionTemplateRemap.get(existing.getPlanDescriptionTemplateId()));
|
||||||
|
@ -1593,25 +1598,36 @@ public class PlanServiceImpl implements PlanService {
|
||||||
List<DescriptionEntity> descriptions = this.queryFactory.query(DescriptionQuery.class)
|
List<DescriptionEntity> descriptions = this.queryFactory.query(DescriptionQuery.class)
|
||||||
.authorize(AuthorizationFlags.AllExceptPublic).planIds(id).isActive(IsActive.Active).collect();
|
.authorize(AuthorizationFlags.AllExceptPublic).planIds(id).isActive(IsActive.Active).collect();
|
||||||
|
|
||||||
|
if (!this.conventionService.isListNullOrEmpty(descriptions)) {
|
||||||
|
List<DescriptionStatusEntity> statusEntities = this.queryFactory.query(DescriptionStatusQuery.class).authorize(AuthorizationFlags.AllExceptPublic).ids(descriptions.stream().map(DescriptionEntity::getStatusId).distinct().toList()).isActive(IsActive.Active).collect();
|
||||||
|
|
||||||
|
if (this.conventionService.isListNullOrEmpty(statusEntities)) throw new MyApplicationException("Not found description statuses");
|
||||||
|
DescriptionStatusEntity finalizedStatusEntity = this.queryFactory.query(DescriptionStatusQuery.class).disableTracking().internalStatuses(DescriptionStatus.Finalized).isActive(IsActive.Active).firstAs(new BaseFieldSet().ensure(org.opencdmp.model.descriptionstatus.DescriptionStatus._id));
|
||||||
|
if (finalizedStatusEntity == null) throw new MyApplicationException("finalized status not found");
|
||||||
|
|
||||||
|
DescriptionStatusEntity canceledStatusEntity = this.queryFactory.query(DescriptionStatusQuery.class).disableTracking().internalStatuses(DescriptionStatus.Canceled).isActive(IsActive.Active).firstAs(new BaseFieldSet().ensure(org.opencdmp.model.descriptionstatus.DescriptionStatus._id));
|
||||||
|
if (canceledStatusEntity == null) throw new MyApplicationException("canceled status not found");
|
||||||
for (DescriptionEntity description: descriptions) {
|
for (DescriptionEntity description: descriptions) {
|
||||||
|
DescriptionStatusEntity currentStatusEntity = statusEntities.stream().filter(x -> x.getId().equals(description.getStatusId())).findFirst().orElse(null);
|
||||||
if (descriptionIds.contains(description.getId())){
|
if (descriptionIds.contains(description.getId())){
|
||||||
// description to be finalized
|
// description to be finalized
|
||||||
if (description.getStatus().equals(DescriptionStatus.Finalized)){
|
if (currentStatusEntity != null && currentStatusEntity.getInternalStatus()!= null && currentStatusEntity.getInternalStatus().equals(DescriptionStatus.Finalized)){
|
||||||
throw new MyApplicationException("Description is already finalized");
|
throw new MyApplicationException("Description is already finalized");
|
||||||
}
|
}
|
||||||
if (this.descriptionService.validate(List.of(description.getId())).getFirst().getResult().equals(DescriptionValidationOutput.Invalid)){
|
if (this.descriptionService.validate(List.of(description.getId())).getFirst().getResult().equals(DescriptionValidationOutput.Invalid)){
|
||||||
throw new MyApplicationException("Description is invalid");
|
throw new MyApplicationException("Description is invalid");
|
||||||
}
|
}
|
||||||
description.setStatus(DescriptionStatus.Finalized);
|
if (finalizedStatusEntity != null) description.setStatusId(finalizedStatusEntity.getId());
|
||||||
description.setUpdatedAt(Instant.now());
|
description.setUpdatedAt(Instant.now());
|
||||||
description.setFinalizedAt(Instant.now());
|
description.setFinalizedAt(Instant.now());
|
||||||
this.entityManager.merge(description);
|
this.entityManager.merge(description);
|
||||||
} else if (description.getStatus().equals(DescriptionStatus.Draft)) {
|
} else if (currentStatusEntity != null && currentStatusEntity.getInternalStatus()!= null && !currentStatusEntity.getInternalStatus().equals(DescriptionStatus.Finalized)) {
|
||||||
// description to be canceled
|
// description to be canceled
|
||||||
description.setStatus(DescriptionStatus.Canceled);
|
description.setStatusId(canceledStatusEntity.getId());
|
||||||
this.deleterFactory.deleter(DescriptionDeleter.class).delete(List.of(description), true);
|
this.deleterFactory.deleter(DescriptionDeleter.class).delete(List.of(description), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PlanStatus previousStatus = plan.getStatus();
|
PlanStatus previousStatus = plan.getStatus();
|
||||||
plan.setStatus(PlanStatus.Finalized);
|
plan.setStatus(PlanStatus.Finalized);
|
||||||
|
|
|
@ -20,6 +20,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||||
import jakarta.xml.bind.JAXBException;
|
import jakarta.xml.bind.JAXBException;
|
||||||
import org.opencdmp.audit.AuditableAction;
|
import org.opencdmp.audit.AuditableAction;
|
||||||
import org.opencdmp.authorization.AuthorizationFlags;
|
import org.opencdmp.authorization.AuthorizationFlags;
|
||||||
|
import org.opencdmp.commons.enums.IsActive;
|
||||||
import org.opencdmp.controllers.swagger.SwaggerHelpers;
|
import org.opencdmp.controllers.swagger.SwaggerHelpers;
|
||||||
import org.opencdmp.controllers.swagger.annotation.OperationWithTenantHeader;
|
import org.opencdmp.controllers.swagger.annotation.OperationWithTenantHeader;
|
||||||
import org.opencdmp.controllers.swagger.annotation.Swagger400;
|
import org.opencdmp.controllers.swagger.annotation.Swagger400;
|
||||||
|
@ -27,11 +28,15 @@ import org.opencdmp.controllers.swagger.annotation.Swagger404;
|
||||||
import org.opencdmp.controllers.swagger.annotation.SwaggerCommonErrorResponses;
|
import org.opencdmp.controllers.swagger.annotation.SwaggerCommonErrorResponses;
|
||||||
import org.opencdmp.data.DescriptionStatusEntity;
|
import org.opencdmp.data.DescriptionStatusEntity;
|
||||||
import org.opencdmp.model.builder.descriptionstatus.DescriptionStatusBuilder;
|
import org.opencdmp.model.builder.descriptionstatus.DescriptionStatusBuilder;
|
||||||
|
import org.opencdmp.model.builder.descriptionworkflow.DescriptionWorkflowBuilder;
|
||||||
import org.opencdmp.model.censorship.descriptionstatus.DescriptionStatusCensor;
|
import org.opencdmp.model.censorship.descriptionstatus.DescriptionStatusCensor;
|
||||||
|
import org.opencdmp.model.censorship.descriptionworkflow.DescriptionWorkflowCensor;
|
||||||
import org.opencdmp.model.descriptionstatus.DescriptionStatus;
|
import org.opencdmp.model.descriptionstatus.DescriptionStatus;
|
||||||
|
import org.opencdmp.model.descriptionworkflow.DescriptionWorkflow;
|
||||||
import org.opencdmp.model.persist.descriptionstatus.DescriptionStatusPersist;
|
import org.opencdmp.model.persist.descriptionstatus.DescriptionStatusPersist;
|
||||||
import org.opencdmp.model.result.QueryResult;
|
import org.opencdmp.model.result.QueryResult;
|
||||||
import org.opencdmp.query.DescriptionStatusQuery;
|
import org.opencdmp.query.DescriptionStatusQuery;
|
||||||
|
import org.opencdmp.query.DescriptionWorkflowQuery;
|
||||||
import org.opencdmp.query.lookup.DescriptionStatusLookup;
|
import org.opencdmp.query.lookup.DescriptionStatusLookup;
|
||||||
import org.opencdmp.service.descriptionstatus.DescriptionStatusService;
|
import org.opencdmp.service.descriptionstatus.DescriptionStatusService;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -183,4 +188,23 @@ public class DescriptionStatusController {
|
||||||
|
|
||||||
this.auditService.track(AuditableAction.DescriptionStatus_Delete, "id", id);
|
this.auditService.track(AuditableAction.DescriptionStatus_Delete, "id", id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("available-transitions/{descriptionId}")
|
||||||
|
@OperationWithTenantHeader(summary = "Get available status transitions for description", description = "",
|
||||||
|
responses = @ApiResponse(description = "OK", responseCode = "200", content = @Content(
|
||||||
|
schema = @Schema(
|
||||||
|
implementation = DescriptionWorkflow.class
|
||||||
|
))
|
||||||
|
))
|
||||||
|
@Swagger404
|
||||||
|
public List<DescriptionStatus> GetAvailableTransitions(
|
||||||
|
@Parameter(name = "descriptionId", description = "The id of description", example = "c0c163dc-2965-45a5-9608-f76030578609", required = true) @PathVariable UUID descriptionId
|
||||||
|
) throws InvalidApplicationException {
|
||||||
|
logger.debug(new MapLogEntry("retrieving available statuses" + DescriptionStatus.class.getSimpleName()));
|
||||||
|
|
||||||
|
List<DescriptionStatus> availableTransitionStatuses = this.descriptionStatusService.getAvailableTransitionStatuses(descriptionId);
|
||||||
|
|
||||||
|
this.auditService.track(AuditableAction.DescriptionStatus_Delete, "descriptionId", descriptionId);
|
||||||
|
return availableTransitionStatuses;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,11 @@ import { Reference, ReferencePersist } from "../reference/reference";
|
||||||
import { Tag, TagPersist } from "../tag/tag";
|
import { Tag, TagPersist } from "../tag/tag";
|
||||||
import { User } from "../user/user";
|
import { User } from "../user/user";
|
||||||
import { AppPermission } from "@app/core/common/enum/permission.enum";
|
import { AppPermission } from "@app/core/common/enum/permission.enum";
|
||||||
|
import { DescriptionStatus } from "../description-status/description-status";
|
||||||
|
|
||||||
export interface Description extends BaseDescription {
|
export interface Description extends BaseDescription {
|
||||||
label?: string;
|
label?: string;
|
||||||
|
status?: DescriptionStatus;
|
||||||
properties?: DescriptionPropertyDefinition;
|
properties?: DescriptionPropertyDefinition;
|
||||||
description?: string;
|
description?: string;
|
||||||
createdBy?: User;
|
createdBy?: User;
|
||||||
|
@ -76,7 +78,7 @@ export interface DescriptionPersist extends BaseEntityPersist {
|
||||||
planId: Guid;
|
planId: Guid;
|
||||||
planDescriptionTemplateId: Guid;
|
planDescriptionTemplateId: Guid;
|
||||||
descriptionTemplateId: Guid;
|
descriptionTemplateId: Guid;
|
||||||
status: DescriptionStatusEnum;
|
statusId: Guid;
|
||||||
description: string;
|
description: string;
|
||||||
properties: DescriptionPropertyDefinitionPersist;
|
properties: DescriptionPropertyDefinitionPersist;
|
||||||
tags: string[];
|
tags: string[];
|
||||||
|
@ -120,7 +122,7 @@ export interface DescriptionReferencePersist {
|
||||||
|
|
||||||
export interface DescriptionStatusPersist {
|
export interface DescriptionStatusPersist {
|
||||||
id: Guid;
|
id: Guid;
|
||||||
status: DescriptionStatusEnum;
|
statusId?: Guid;
|
||||||
hash: string;
|
hash: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,7 +132,7 @@ export interface DescriptionStatusPersist {
|
||||||
|
|
||||||
export interface PublicDescription extends BaseDescription {
|
export interface PublicDescription extends BaseDescription {
|
||||||
label?: string;
|
label?: string;
|
||||||
status?: DescriptionStatusEnum;
|
status?: PublicDescriptionStatus;
|
||||||
description?: string;
|
description?: string;
|
||||||
finalizedAt?: Date;
|
finalizedAt?: Date;
|
||||||
descriptionTemplate?: PublicDescriptionTemplate;
|
descriptionTemplate?: PublicDescriptionTemplate;
|
||||||
|
@ -148,6 +150,13 @@ export interface PublicDescriptionTemplate {
|
||||||
label: string;
|
label: string;
|
||||||
description: string;
|
description: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface PublicDescriptionStatus {
|
||||||
|
id: Guid;
|
||||||
|
name: string;
|
||||||
|
internalStatus: DescriptionStatusEnum;
|
||||||
|
}
|
||||||
|
|
||||||
export interface DescriptionSectionPermissionResolver {
|
export interface DescriptionSectionPermissionResolver {
|
||||||
planId: Guid;
|
planId: Guid;
|
||||||
sectionIds: Guid[];
|
sectionIds: Guid[];
|
||||||
|
@ -161,5 +170,4 @@ export interface UpdateDescriptionTemplatePersist {
|
||||||
|
|
||||||
export interface BaseDescription extends BaseEntity {
|
export interface BaseDescription extends BaseEntity {
|
||||||
tenantId?: Guid;
|
tenantId?: Guid;
|
||||||
status?: DescriptionStatusEnum;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +56,15 @@ export class DescriptionStatusService {
|
||||||
catchError((error: any) => throwError(() => error)));
|
catchError((error: any) => throwError(() => error)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getAvailableTransitions(descriptionId: Guid, reqFields: string[] = []): Observable<Array<DescriptionStatus>> {
|
||||||
|
const url = `${this.apiBase}/available-transitions/${descriptionId}`;
|
||||||
|
const options = { params: { f: reqFields } };
|
||||||
|
|
||||||
|
return this.http
|
||||||
|
.get<Array<DescriptionStatus>>(url, options).pipe(
|
||||||
|
catchError((error: any) => throwError(() => error)));
|
||||||
|
}
|
||||||
|
|
||||||
buildLookup(params: {
|
buildLookup(params: {
|
||||||
like?: string,
|
like?: string,
|
||||||
excludedIds?: Guid[],
|
excludedIds?: Guid[],
|
||||||
|
|
|
@ -28,6 +28,7 @@ import { BehaviorSubject } from 'rxjs';
|
||||||
import { debounceTime, map, takeUntil } from 'rxjs/operators';
|
import { debounceTime, map, takeUntil } from 'rxjs/operators';
|
||||||
import { nameof } from 'ts-simple-nameof';
|
import { nameof } from 'ts-simple-nameof';
|
||||||
import { ActivityListingType } from '../dashboard.component';
|
import { ActivityListingType } from '../dashboard.component';
|
||||||
|
import { DescriptionStatus } from '@app/core/model/description-status/description-status';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-recent-edited-activity',
|
selector: 'app-recent-edited-activity',
|
||||||
|
@ -232,16 +233,16 @@ export class RecentEditedActivityComponent extends BaseComponent implements OnIn
|
||||||
if (item.plan){
|
if (item.plan){
|
||||||
if (item.plan.descriptions) {
|
if (item.plan.descriptions) {
|
||||||
if (item.plan.status == PlanStatusEnum.Finalized) {
|
if (item.plan.status == PlanStatusEnum.Finalized) {
|
||||||
item.plan.descriptions = item.plan.descriptions.filter(x => x.isActive === IsActive.Active && x.status === DescriptionStatusEnum.Finalized);
|
item.plan.descriptions = item.plan.descriptions.filter(x => x.isActive === IsActive.Active && x.status?.internalStatus === DescriptionStatusEnum.Finalized);
|
||||||
} else {
|
} else {
|
||||||
item.plan.descriptions = item.plan.descriptions.filter(x => x.isActive === IsActive.Active && x.status != DescriptionStatusEnum.Canceled);
|
item.plan.descriptions = item.plan.descriptions.filter(x => x.isActive === IsActive.Active && x.status?.internalStatus != DescriptionStatusEnum.Canceled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
item.plan.planUsers = item.plan.planUsers.filter(x=> x.isActive === IsActive.Active);
|
item.plan.planUsers = item.plan.planUsers.filter(x=> x.isActive === IsActive.Active);
|
||||||
this.listingItems.push(item);
|
this.listingItems.push(item);
|
||||||
}
|
}
|
||||||
if (item.description){
|
if (item.description){
|
||||||
if (item.description.status != DescriptionStatusEnum.Canceled) this.listingItems.push(item);
|
if (item.description?.status?.internalStatus != DescriptionStatusEnum.Canceled) this.listingItems.push(item);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -288,7 +289,9 @@ export class RecentEditedActivityComponent extends BaseComponent implements OnIn
|
||||||
[nameof<RecentActivityItem>(x => x.plan), nameof<Plan>(x => x.authorizationFlags), AppPermission.EditPlan].join('.'),
|
[nameof<RecentActivityItem>(x => x.plan), nameof<Plan>(x => x.authorizationFlags), AppPermission.EditPlan].join('.'),
|
||||||
[nameof<RecentActivityItem>(x => x.plan), nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.id)].join('.'),
|
[nameof<RecentActivityItem>(x => x.plan), nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.id)].join('.'),
|
||||||
[nameof<RecentActivityItem>(x => x.plan), nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.label)].join('.'),
|
[nameof<RecentActivityItem>(x => x.plan), nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.label)].join('.'),
|
||||||
[nameof<RecentActivityItem>(x => x.plan), nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.status)].join('.'),
|
[nameof<RecentActivityItem>(x => x.plan), nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.id)].join('.'),
|
||||||
|
[nameof<RecentActivityItem>(x => x.plan), nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.name)].join('.'),
|
||||||
|
[nameof<RecentActivityItem>(x => x.plan), nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.internalStatus)].join('.'),
|
||||||
[nameof<RecentActivityItem>(x => x.plan), nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.isActive)].join('.'),
|
[nameof<RecentActivityItem>(x => x.plan), nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.isActive)].join('.'),
|
||||||
[nameof<RecentActivityItem>(x => x.plan), nameof<Plan>(x => x.blueprint), nameof<PlanBlueprint>(x => x.id)].join('.'),
|
[nameof<RecentActivityItem>(x => x.plan), nameof<Plan>(x => x.blueprint), nameof<PlanBlueprint>(x => x.id)].join('.'),
|
||||||
[nameof<RecentActivityItem>(x => x.plan), nameof<Plan>(x => x.blueprint), nameof<PlanBlueprint>(x => x.label)].join('.'),
|
[nameof<RecentActivityItem>(x => x.plan), nameof<Plan>(x => x.blueprint), nameof<PlanBlueprint>(x => x.label)].join('.'),
|
||||||
|
@ -318,7 +321,9 @@ export class RecentEditedActivityComponent extends BaseComponent implements OnIn
|
||||||
return [
|
return [
|
||||||
[nameof<RecentActivityItem>(x => x.description), nameof<Description>(x => x.id)].join('.'),
|
[nameof<RecentActivityItem>(x => x.description), nameof<Description>(x => x.id)].join('.'),
|
||||||
[nameof<RecentActivityItem>(x => x.description), nameof<Description>(x => x.label)].join('.'),
|
[nameof<RecentActivityItem>(x => x.description), nameof<Description>(x => x.label)].join('.'),
|
||||||
[nameof<RecentActivityItem>(x => x.description), nameof<Description>(x => x.status)].join('.'),
|
[nameof<RecentActivityItem>(x => x.description), nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.id)].join('.'),
|
||||||
|
[nameof<RecentActivityItem>(x => x.description), nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.name)].join('.'),
|
||||||
|
[nameof<RecentActivityItem>(x => x.description), nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.internalStatus)].join('.'),
|
||||||
[nameof<RecentActivityItem>(x => x.description), nameof<Description>(x => x.updatedAt)].join('.'),
|
[nameof<RecentActivityItem>(x => x.description), nameof<Description>(x => x.updatedAt)].join('.'),
|
||||||
[nameof<RecentActivityItem>(x => x.description), nameof<Description>(x => x.isActive)].join('.'),
|
[nameof<RecentActivityItem>(x => x.description), nameof<Description>(x => x.isActive)].join('.'),
|
||||||
[nameof<RecentActivityItem>(x => x.description), nameof<Description>(x => x.authorizationFlags), AppPermission.EditDescription].join('.'),
|
[nameof<RecentActivityItem>(x => x.description), nameof<Description>(x => x.authorizationFlags), AppPermission.EditDescription].join('.'),
|
||||||
|
|
|
@ -46,7 +46,7 @@ export class DescriptionBaseFieldsEditorComponent extends BaseComponent {
|
||||||
if (this.description?.descriptionTemplate != null) {
|
if (this.description?.descriptionTemplate != null) {
|
||||||
const isPreviousVersion: boolean = this.description.descriptionTemplate.versionStatus === DescriptionTemplateVersionStatus.Previous;
|
const isPreviousVersion: boolean = this.description.descriptionTemplate.versionStatus === DescriptionTemplateVersionStatus.Previous;
|
||||||
if (isPreviousVersion === true) {
|
if (isPreviousVersion === true) {
|
||||||
if (this.description.status === DescriptionStatusEnum.Draft) {
|
if (this.description.status?.internalStatus === DescriptionStatusEnum.Draft) {
|
||||||
this.openDeprecatedDescriptionTemplateDialog();
|
this.openDeprecatedDescriptionTemplateDialog();
|
||||||
} else {
|
} else {
|
||||||
this.availableDescriptionTemplates.push(this.description.descriptionTemplate);
|
this.availableDescriptionTemplates.push(this.description.descriptionTemplate);
|
||||||
|
|
|
@ -67,9 +67,12 @@
|
||||||
<button [disabled]="saving" mat-menu-item (click)="saveAndClose()" type="button">{{ 'DESCRIPTION-EDITOR.ACTIONS.SAVE-AND-CLOSE' | translate }}</button>
|
<button [disabled]="saving" mat-menu-item (click)="saveAndClose()" type="button">{{ 'DESCRIPTION-EDITOR.ACTIONS.SAVE-AND-CLOSE' | translate }}</button>
|
||||||
<button [disabled]="saving" mat-menu-item (click)="saveAndContinue()" type="button">{{ 'DESCRIPTION-EDITOR.ACTIONS.SAVE-AND-CONTINUE' | translate }}</button>
|
<button [disabled]="saving" mat-menu-item (click)="saveAndContinue()" type="button">{{ 'DESCRIPTION-EDITOR.ACTIONS.SAVE-AND-CONTINUE' | translate }}</button>
|
||||||
</mat-menu>
|
</mat-menu>
|
||||||
<button [disabled]="saving" *ngIf="canEdit && !isLocked && !viewOnly && hasReversableStatus() == false && canEdit" mat-button class="rounded-btn neutral mr-2" type="button" (click)="finalize()">{{ 'DESCRIPTION-EDITOR.ACTIONS.FINALIZE' | translate }}</button>
|
<ng-container *ngIf="availableStatusesTransitions && availableStatusesTransitions.length > 0 && !isLocked && item.id">
|
||||||
|
<button *ngFor='let status of availableStatusesTransitions' [disabled]="saving" mat-button class="rounded-btn neutral mr-2" type="button" (click)="persistStatus(status)">{{ status.name }}</button>
|
||||||
|
</ng-container>
|
||||||
|
<!-- <button [disabled]="saving" *ngIf="canEdit && !isLocked && !viewOnly && hasReversableStatus() == false && canEdit" mat-button class="rounded-btn neutral mr-2" type="button" (click)="finalize()">{{ 'DESCRIPTION-EDITOR.ACTIONS.FINALIZE' | translate }}</button> -->
|
||||||
<button [disabled]="saving" *ngIf="isLocked" mat-button disabled class="rounded-btn neutral cursor-default" type="button">{{ 'PLAN-OVERVIEW.LOCKED' | translate}}</button>
|
<button [disabled]="saving" *ngIf="isLocked" mat-button disabled class="rounded-btn neutral cursor-default" type="button">{{ 'PLAN-OVERVIEW.LOCKED' | translate}}</button>
|
||||||
<button [disabled]="saving" *ngIf="hasReversableStatus() && !isLocked && canEdit" mat-button class="rounded-btn neutral mr-2" (click)="reverse()" type="button">{{ 'DESCRIPTION-EDITOR.ACTIONS.REVERSE' | translate }}</button>
|
<!-- <button [disabled]="saving" *ngIf="hasReversableStatus() && !isLocked && canEdit" mat-button class="rounded-btn neutral mr-2" (click)="reverse()" type="button">{{ 'DESCRIPTION-EDITOR.ACTIONS.REVERSE' | translate }}</button> -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -45,6 +45,8 @@ import { DescriptionEditorEntityResolver } from './resolvers/description-editor-
|
||||||
import { ToCEntry } from './table-of-contents/models/toc-entry';
|
import { ToCEntry } from './table-of-contents/models/toc-entry';
|
||||||
import { TableOfContentsService } from './table-of-contents/services/table-of-contents-service';
|
import { TableOfContentsService } from './table-of-contents/services/table-of-contents-service';
|
||||||
import { TableOfContentsComponent } from './table-of-contents/table-of-contents.component';
|
import { TableOfContentsComponent } from './table-of-contents/table-of-contents.component';
|
||||||
|
import { DescriptionStatusService } from '@app/core/services/description-status/description-status.service';
|
||||||
|
import { DescriptionStatus } from '@app/core/model/description-status/description-status';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-description-editor-component',
|
selector: 'app-description-editor-component',
|
||||||
|
@ -82,6 +84,9 @@ export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorMode
|
||||||
private initialTemplateId: string = Guid.EMPTY;
|
private initialTemplateId: string = Guid.EMPTY;
|
||||||
private permissionPerSection: Map<Guid, string[]>;
|
private permissionPerSection: Map<Guid, string[]>;
|
||||||
|
|
||||||
|
availableStatusesTransitions: DescriptionStatus[];
|
||||||
|
oldStatusId: Guid;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
// BaseFormEditor injected dependencies
|
// BaseFormEditor injected dependencies
|
||||||
public routerUtils: RouterUtilsService,
|
public routerUtils: RouterUtilsService,
|
||||||
|
@ -111,6 +116,7 @@ export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorMode
|
||||||
private tableOfContentsService: TableOfContentsService,
|
private tableOfContentsService: TableOfContentsService,
|
||||||
private descriptionFormService: DescriptionFormService,
|
private descriptionFormService: DescriptionFormService,
|
||||||
private formAnnotationService: FormAnnotationService,
|
private formAnnotationService: FormAnnotationService,
|
||||||
|
private descriptionStatusService: DescriptionStatusService
|
||||||
) {
|
) {
|
||||||
const descriptionLabel: string = route.snapshot.data['entity']?.label;
|
const descriptionLabel: string = route.snapshot.data['entity']?.label;
|
||||||
if (descriptionLabel) {
|
if (descriptionLabel) {
|
||||||
|
@ -190,7 +196,8 @@ export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorMode
|
||||||
}
|
}
|
||||||
if (this.route.snapshot.url[1] && this.route.snapshot.url[1].path == 'finalize' && !this.lockStatus && !this.viewOnly) {
|
if (this.route.snapshot.url[1] && this.route.snapshot.url[1].path == 'finalize' && !this.lockStatus && !this.viewOnly) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.finalize();
|
const finalizedStatus = this.availableStatusesTransitions?.find(x => x.internalStatus === DescriptionStatusEnum.Finalized) || null;
|
||||||
|
if (finalizedStatus) this.finalize(finalizedStatus.id);
|
||||||
}, 0);
|
}, 0);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -215,6 +222,10 @@ export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorMode
|
||||||
prepareForm(data: Description) {
|
prepareForm(data: Description) {
|
||||||
try {
|
try {
|
||||||
this.editorModel = data ? new DescriptionEditorModel().fromModel(data, data.descriptionTemplate) : new DescriptionEditorModel();
|
this.editorModel = data ? new DescriptionEditorModel().fromModel(data, data.descriptionTemplate) : new DescriptionEditorModel();
|
||||||
|
if (data) {
|
||||||
|
if (data.id) this.getAvailableStatuses(data.id);
|
||||||
|
if (data.status?.id) this.oldStatusId = data.status.id
|
||||||
|
}
|
||||||
if (data && data?.plan?.planUsers) data.plan.planUsers = data.plan.planUsers.filter(x => x.isActive === IsActive.Active);
|
if (data && data?.plan?.planUsers) data.plan.planUsers = data.plan.planUsers.filter(x => x.isActive === IsActive.Active);
|
||||||
this.item = data;
|
this.item = data;
|
||||||
this.initialTemplateId = data?.descriptionTemplate?.id?.toString();
|
this.initialTemplateId = data?.descriptionTemplate?.id?.toString();
|
||||||
|
@ -227,6 +238,13 @@ export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorMode
|
||||||
}
|
}
|
||||||
this.isDeleted = data ? data.isActive === IsActive.Inactive : false;
|
this.isDeleted = data ? data.isActive === IsActive.Inactive : false;
|
||||||
this.buildForm();
|
this.buildForm();
|
||||||
|
if (data?.status?.internalStatus == DescriptionStatusEnum.Finalized || this.isDeleted || !this.canEdit) {
|
||||||
|
this.viewOnly = true;
|
||||||
|
this.isFinalized = true;
|
||||||
|
this.formGroup.disable();
|
||||||
|
} else {
|
||||||
|
this.viewOnly = false;
|
||||||
|
}
|
||||||
if (this.isDeleted || (this.formGroup && this.editorModel.belongsToCurrentTenant == false)) {
|
if (this.isDeleted || (this.formGroup && this.editorModel.belongsToCurrentTenant == false)) {
|
||||||
this.formGroup.disable();
|
this.formGroup.disable();
|
||||||
this.canEdit = false;
|
this.canEdit = false;
|
||||||
|
@ -245,17 +263,19 @@ export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorMode
|
||||||
|
|
||||||
// this.selectedSystemFields = this.selectedSystemFieldDisabled();
|
// this.selectedSystemFields = this.selectedSystemFieldDisabled();
|
||||||
this.descriptionEditorService.setValidationErrorModel(this.editorModel.validationErrorModel);
|
this.descriptionEditorService.setValidationErrorModel(this.editorModel.validationErrorModel);
|
||||||
if (this.editorModel.status == DescriptionStatusEnum.Finalized || this.isDeleted || !this.canEdit) {
|
|
||||||
this.viewOnly = true;
|
|
||||||
this.isFinalized = this.editorModel.status == DescriptionStatusEnum.Finalized;
|
|
||||||
this.formGroup.disable();
|
|
||||||
} else {
|
|
||||||
this.viewOnly = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.registerFormListeners();
|
this.registerFormListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getAvailableStatuses(id: Guid){
|
||||||
|
this.descriptionStatusService.getAvailableTransitions(id).pipe(takeUntil(this._destroyed))
|
||||||
|
.subscribe(
|
||||||
|
(statuses) => {
|
||||||
|
this.availableStatusesTransitions = statuses;
|
||||||
|
},
|
||||||
|
(error) => this.httpErrorHandlingService.handleBackedRequestError(error)
|
||||||
|
); }
|
||||||
|
|
||||||
calculateMultiplicityRejectedPlanDescriptionTemplates(section: PlanBlueprintDefinitionSection, descriptions: Description[]): PlanDescriptionTemplate[] {
|
calculateMultiplicityRejectedPlanDescriptionTemplates(section: PlanBlueprintDefinitionSection, descriptions: Description[]): PlanDescriptionTemplate[] {
|
||||||
if (section.descriptionTemplates?.length > 0) {
|
if (section.descriptionTemplates?.length > 0) {
|
||||||
descriptions = descriptions?.filter(x => x?.planDescriptionTemplate?.sectionId === section.id) || [];
|
descriptions = descriptions?.filter(x => x?.planDescriptionTemplate?.sectionId === section.id) || [];
|
||||||
|
@ -302,17 +322,18 @@ export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorMode
|
||||||
|
|
||||||
persistEntity(onSuccess?: (response) => void): void {
|
persistEntity(onSuccess?: (response) => void): void {
|
||||||
const formData = this.formService.getValue(this.formGroup.value) as DescriptionPersist;
|
const formData = this.formService.getValue(this.formGroup.value) as DescriptionPersist;
|
||||||
|
const finalizedStatus = this.availableStatusesTransitions?.find(x => x.internalStatus === DescriptionStatusEnum.Finalized) || null;
|
||||||
|
|
||||||
this.descriptionService.persist(formData)
|
this.descriptionService.persist(formData)
|
||||||
.pipe(takeUntil(this._destroyed)).subscribe(
|
.pipe(takeUntil(this._destroyed)).subscribe(
|
||||||
complete => {
|
complete => {
|
||||||
onSuccess ? onSuccess(complete) : this.onCallbackSuccess(complete);
|
onSuccess ? onSuccess(complete) : this.onCallbackSuccess(complete);
|
||||||
this.descriptionIsOnceSaved = true;
|
this.descriptionIsOnceSaved = true;
|
||||||
if (this.formGroup.get('status').value == DescriptionStatusEnum.Finalized) this.isFinalized = true;
|
if (finalizedStatus && this.formGroup.get('statusId').value == finalizedStatus.id) this.isFinalized = true;
|
||||||
},
|
},
|
||||||
error => {
|
error => {
|
||||||
if (this.formGroup.get('status').value == DescriptionStatusEnum.Finalized) {
|
if (finalizedStatus && this.formGroup.get('statusId').value == finalizedStatus.id) {
|
||||||
this.formGroup.get('status').setValue(DescriptionStatusEnum.Draft);
|
this.formGroup.get('statusId').setValue(this.oldStatusId);
|
||||||
this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-FINALIZE'), SnackBarNotificationLevel.Error);
|
this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-FINALIZE'), SnackBarNotificationLevel.Error);
|
||||||
} else {
|
} else {
|
||||||
this.onCallbackError(error);
|
this.onCallbackError(error);
|
||||||
|
@ -324,7 +345,7 @@ export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorMode
|
||||||
formSubmit(onSuccess?: (response) => void): void {
|
formSubmit(onSuccess?: (response) => void): void {
|
||||||
this.formService.removeAllBackEndErrors(this.formGroup);
|
this.formService.removeAllBackEndErrors(this.formGroup);
|
||||||
if (this.formGroup.get('label').valid && this.formGroup.get('planId').valid && this.formGroup.get('planDescriptionTemplateId').valid
|
if (this.formGroup.get('label').valid && this.formGroup.get('planId').valid && this.formGroup.get('planDescriptionTemplateId').valid
|
||||||
&& this.formGroup.get('descriptionTemplateId').valid && this.formGroup.get('status').valid) {
|
&& this.formGroup.get('descriptionTemplateId').valid) {// && this.formGroup.get('statusId').valid) {
|
||||||
this.persistEntity(onSuccess);
|
this.persistEntity(onSuccess);
|
||||||
} else {
|
} else {
|
||||||
const errorMessages = this._buildSemiFormErrorMessages();
|
const errorMessages = this._buildSemiFormErrorMessages();
|
||||||
|
@ -698,7 +719,19 @@ export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorMode
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
finalize() {
|
persistStatus(status: DescriptionStatus) {
|
||||||
|
if (status.internalStatus != null && status.internalStatus === DescriptionStatusEnum.Finalized) {
|
||||||
|
this.finalize(status.id);
|
||||||
|
} else if (status.internalStatus != null && this.item.status.internalStatus === DescriptionStatusEnum.Finalized){
|
||||||
|
this.reverse(status.id);
|
||||||
|
} else {
|
||||||
|
// other statuses
|
||||||
|
this.formGroup.get('statusId').setValue(status.id);
|
||||||
|
this.persistEntity();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
finalize(statusId: Guid) {
|
||||||
this.formService.removeAllBackEndErrors(this.formGroup);
|
this.formService.removeAllBackEndErrors(this.formGroup);
|
||||||
this.formService.touchAllFormFields(this.formGroup);
|
this.formService.touchAllFormFields(this.formGroup);
|
||||||
this.formService.validateAllFormFields(this.formGroup);
|
this.formService.validateAllFormFields(this.formGroup);
|
||||||
|
@ -727,13 +760,13 @@ export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorMode
|
||||||
});
|
});
|
||||||
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
|
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
|
||||||
if (result) {
|
if (result) {
|
||||||
this.formGroup.get('status').setValue(DescriptionStatusEnum.Finalized);
|
this.formGroup.get('statusId').setValue(statusId);
|
||||||
this.persistEntity();
|
this.persistEntity();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
reverse() {
|
reverse(statusId: Guid) {
|
||||||
const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
|
const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
|
||||||
restoreFocus: false,
|
restoreFocus: false,
|
||||||
data: {
|
data: {
|
||||||
|
@ -747,7 +780,7 @@ export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorMode
|
||||||
if (result) {
|
if (result) {
|
||||||
const planUserRemovePersist: DescriptionStatusPersist = {
|
const planUserRemovePersist: DescriptionStatusPersist = {
|
||||||
id: this.formGroup.get('id').value,
|
id: this.formGroup.get('id').value,
|
||||||
status: DescriptionStatusEnum.Draft,
|
statusId: statusId,
|
||||||
hash: this.formGroup.get('hash').value
|
hash: this.formGroup.get('hash').value
|
||||||
};
|
};
|
||||||
this.descriptionService.persistStatus(planUserRemovePersist, DescriptionEditorEntityResolver.lookupFields()).pipe(takeUntil(this._destroyed))
|
this.descriptionService.persistStatus(planUserRemovePersist, DescriptionEditorEntityResolver.lookupFields()).pipe(takeUntil(this._destroyed))
|
||||||
|
|
|
@ -18,7 +18,7 @@ export class DescriptionEditorModel extends BaseEditorModel implements Descripti
|
||||||
planId: Guid;
|
planId: Guid;
|
||||||
planDescriptionTemplateId: Guid;
|
planDescriptionTemplateId: Guid;
|
||||||
descriptionTemplateId: Guid;
|
descriptionTemplateId: Guid;
|
||||||
status: DescriptionStatusEnum;
|
statusId: Guid;
|
||||||
description: string;
|
description: string;
|
||||||
properties: DescriptionPropertyDefinitionEditorModel = new DescriptionPropertyDefinitionEditorModel(this.validationErrorModel);
|
properties: DescriptionPropertyDefinitionEditorModel = new DescriptionPropertyDefinitionEditorModel(this.validationErrorModel);
|
||||||
tags: string[] = [];
|
tags: string[] = [];
|
||||||
|
@ -36,7 +36,7 @@ export class DescriptionEditorModel extends BaseEditorModel implements Descripti
|
||||||
this.planId = item.plan?.id;
|
this.planId = item.plan?.id;
|
||||||
this.planDescriptionTemplateId = item.planDescriptionTemplate?.id;
|
this.planDescriptionTemplateId = item.planDescriptionTemplate?.id;
|
||||||
this.descriptionTemplateId = item.descriptionTemplate?.id;
|
this.descriptionTemplateId = item.descriptionTemplate?.id;
|
||||||
this.status = item.status ?? DescriptionStatusEnum.Draft;
|
this.statusId = item.status?.id;
|
||||||
this.description = item.description;
|
this.description = item.description;
|
||||||
this.tags = item.descriptionTags?.filter(x => x.isActive === IsActive.Active).map(x => x.tag?.label);
|
this.tags = item.descriptionTags?.filter(x => x.isActive === IsActive.Active).map(x => x.tag?.label);
|
||||||
this.properties = new DescriptionPropertyDefinitionEditorModel(this.validationErrorModel).fromModel(item.properties, descriptionTemplate, item.descriptionReferences);
|
this.properties = new DescriptionPropertyDefinitionEditorModel(this.validationErrorModel).fromModel(item.properties, descriptionTemplate, item.descriptionReferences);
|
||||||
|
@ -53,7 +53,7 @@ export class DescriptionEditorModel extends BaseEditorModel implements Descripti
|
||||||
planId: [{ value: this.planId, disabled: disabled }, context.getValidation('planId').validators],
|
planId: [{ value: this.planId, disabled: disabled }, context.getValidation('planId').validators],
|
||||||
planDescriptionTemplateId: [{ value: this.planDescriptionTemplateId, disabled: disabled }, context.getValidation('planDescriptionTemplateId').validators],
|
planDescriptionTemplateId: [{ value: this.planDescriptionTemplateId, disabled: disabled }, context.getValidation('planDescriptionTemplateId').validators],
|
||||||
descriptionTemplateId: [{ value: this.descriptionTemplateId, disabled: disabled }, context.getValidation('descriptionTemplateId').validators],
|
descriptionTemplateId: [{ value: this.descriptionTemplateId, disabled: disabled }, context.getValidation('descriptionTemplateId').validators],
|
||||||
status: [{ value: this.status, disabled: disabled }, context.getValidation('status').validators],
|
statusId: [{ value: this.statusId, disabled: disabled }, context.getValidation('statusId').validators],
|
||||||
description: [{ value: this.description, disabled: disabled }, context.getValidation('description').validators],
|
description: [{ value: this.description, disabled: disabled }, context.getValidation('description').validators],
|
||||||
tags: [{ value: this.tags, disabled: disabled }, context.getValidation('tags').validators],
|
tags: [{ value: this.tags, disabled: disabled }, context.getValidation('tags').validators],
|
||||||
properties: this.buildProperties(visibilityRulesService),
|
properties: this.buildProperties(visibilityRulesService),
|
||||||
|
@ -76,7 +76,7 @@ export class DescriptionEditorModel extends BaseEditorModel implements Descripti
|
||||||
baseValidationArray.push({ key: 'planId', validators: [CustomValidators.required(), BackendErrorValidator(this.validationErrorModel, 'planId')] });
|
baseValidationArray.push({ key: 'planId', validators: [CustomValidators.required(), BackendErrorValidator(this.validationErrorModel, 'planId')] });
|
||||||
baseValidationArray.push({ key: 'planDescriptionTemplateId', validators: [CustomValidators.required(), BackendErrorValidator(this.validationErrorModel, 'planDescriptionTemplateId')] });
|
baseValidationArray.push({ key: 'planDescriptionTemplateId', validators: [CustomValidators.required(), BackendErrorValidator(this.validationErrorModel, 'planDescriptionTemplateId')] });
|
||||||
baseValidationArray.push({ key: 'descriptionTemplateId', validators: [CustomValidators.required(), BackendErrorValidator(this.validationErrorModel, 'descriptionTemplateId')] });
|
baseValidationArray.push({ key: 'descriptionTemplateId', validators: [CustomValidators.required(), BackendErrorValidator(this.validationErrorModel, 'descriptionTemplateId')] });
|
||||||
baseValidationArray.push({ key: 'status', validators: [CustomValidators.required(), BackendErrorValidator(this.validationErrorModel, 'status')] });
|
baseValidationArray.push({ key: 'statusId', validators: [BackendErrorValidator(this.validationErrorModel, 'statusId')] });
|
||||||
baseValidationArray.push({ key: 'description', validators: [BackendErrorValidator(this.validationErrorModel, 'description')] });
|
baseValidationArray.push({ key: 'description', validators: [BackendErrorValidator(this.validationErrorModel, 'description')] });
|
||||||
baseValidationArray.push({ key: 'tags', validators: [BackendErrorValidator(this.validationErrorModel, 'tags')] });
|
baseValidationArray.push({ key: 'tags', validators: [BackendErrorValidator(this.validationErrorModel, 'tags')] });
|
||||||
baseValidationArray.push({ key: 'hash', validators: [] });
|
baseValidationArray.push({ key: 'hash', validators: [] });
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
|
import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
|
||||||
import { DescriptionStatusEnum } from '@app/core/common/enum/description-status';
|
|
||||||
import { IsActive } from '@app/core/common/enum/is-active.enum';
|
import { IsActive } from '@app/core/common/enum/is-active.enum';
|
||||||
import { AppPermission } from '@app/core/common/enum/permission.enum';
|
import { AppPermission } from '@app/core/common/enum/permission.enum';
|
||||||
|
import { DescriptionStatus } from '@app/core/model/description-status/description-status';
|
||||||
import { DescriptionTemplate } from '@app/core/model/description-template/description-template';
|
import { DescriptionTemplate } from '@app/core/model/description-template/description-template';
|
||||||
import { Description, DescriptionExternalIdentifier, DescriptionField, DescriptionPropertyDefinition, DescriptionPropertyDefinitionFieldSet, DescriptionPropertyDefinitionFieldSetItem, DescriptionReference, DescriptionReferenceData, DescriptionTag } from '@app/core/model/description/description';
|
import { Description, DescriptionExternalIdentifier, DescriptionField, DescriptionPropertyDefinition, DescriptionPropertyDefinitionFieldSet, DescriptionPropertyDefinitionFieldSetItem, DescriptionReference, DescriptionReferenceData, DescriptionTag } from '@app/core/model/description/description';
|
||||||
import { DescriptionTemplatesInSection, PlanBlueprint, PlanBlueprintDefinition, PlanBlueprintDefinitionSection } from '@app/core/model/plan-blueprint/plan-blueprint';
|
import { DescriptionTemplatesInSection, PlanBlueprint, PlanBlueprintDefinition, PlanBlueprintDefinitionSection } from '@app/core/model/plan-blueprint/plan-blueprint';
|
||||||
|
@ -52,9 +52,10 @@ export class DescriptionEditorEntityResolver extends BaseEditorResolver {
|
||||||
...BaseEditorResolver.lookupFields(),
|
...BaseEditorResolver.lookupFields(),
|
||||||
nameof<Description>(x => x.id),
|
nameof<Description>(x => x.id),
|
||||||
nameof<Description>(x => x.label),
|
nameof<Description>(x => x.label),
|
||||||
nameof<Description>(x => x.status),
|
|
||||||
nameof<Description>(x => x.description),
|
nameof<Description>(x => x.description),
|
||||||
nameof<Description>(x => x.status),
|
[nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.id)].join('.'),
|
||||||
|
[nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.name)].join('.'),
|
||||||
|
[nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.internalStatus)].join('.'),
|
||||||
|
|
||||||
[nameof<Description>(x => x.authorizationFlags), AppPermission.EditDescription].join('.'),
|
[nameof<Description>(x => x.authorizationFlags), AppPermission.EditDescription].join('.'),
|
||||||
[nameof<Description>(x => x.authorizationFlags), AppPermission.DeleteDescription].join('.'),
|
[nameof<Description>(x => x.authorizationFlags), AppPermission.DeleteDescription].join('.'),
|
||||||
|
@ -203,7 +204,7 @@ export class DescriptionEditorEntityResolver extends BaseEditorResolver {
|
||||||
description.hash = null;
|
description.hash = null;
|
||||||
description.isActive = IsActive.Active;
|
description.isActive = IsActive.Active;
|
||||||
description.belongsToCurrentTenant = true;
|
description.belongsToCurrentTenant = true;
|
||||||
description.status = DescriptionStatusEnum.Draft;
|
description.status = null;
|
||||||
description.plan = plan;
|
description.plan = plan;
|
||||||
description.planDescriptionTemplate = {
|
description.planDescriptionTemplate = {
|
||||||
id: plan.planDescriptionTemplates.filter(x => x.sectionId == Guid.parse(planSectionId) && x.descriptionTemplateGroupId == description.descriptionTemplate.groupId)[0].id,
|
id: plan.planDescriptionTemplates.filter(x => x.sectionId == Guid.parse(planSectionId) && x.descriptionTemplateGroupId == description.descriptionTemplate.groupId)[0].id,
|
||||||
|
|
|
@ -43,6 +43,7 @@ import { InterceptorType } from '@common/http/interceptors/interceptor-type';
|
||||||
import { PrincipalService } from '@app/core/services/http/principal.service';
|
import { PrincipalService } from '@app/core/services/http/principal.service';
|
||||||
import { DescriptionListingFilters } from './filtering/description-filter.component';
|
import { DescriptionListingFilters } from './filtering/description-filter.component';
|
||||||
import { MatSelectChange } from '@angular/material/select';
|
import { MatSelectChange } from '@angular/material/select';
|
||||||
|
import { DescriptionStatus } from '@app/core/model/description-status/description-status';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-description-listing-component',
|
selector: 'app-description-listing-component',
|
||||||
|
@ -490,7 +491,9 @@ export class DescriptionListingComponent extends BaseListingComponent<BaseDescri
|
||||||
nameof<Description>(x => x.id),
|
nameof<Description>(x => x.id),
|
||||||
nameof<Description>(x => x.tenantId),
|
nameof<Description>(x => x.tenantId),
|
||||||
nameof<Description>(x => x.label),
|
nameof<Description>(x => x.label),
|
||||||
nameof<Description>(x => x.status),
|
[nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.id)].join('.'),
|
||||||
|
[nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.name)].join('.'),
|
||||||
|
[nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.internalStatus)].join('.'),
|
||||||
nameof<Description>(x => x.updatedAt),
|
nameof<Description>(x => x.updatedAt),
|
||||||
nameof<Description>(x => x.belongsToCurrentTenant),
|
nameof<Description>(x => x.belongsToCurrentTenant),
|
||||||
nameof<Description>(x => x.finalizedAt),
|
nameof<Description>(x => x.finalizedAt),
|
||||||
|
|
|
@ -13,15 +13,18 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="description.status === descriptionStatusEnum.Finalized" class="col-auto description-title">{{description.label}}</div>
|
<div *ngIf="description.status.internalStatus === descriptionStatusEnum.Finalized" class="col-auto description-title">{{description.label}}</div>
|
||||||
<div *ngIf="description.status === descriptionStatusEnum.Draft" class="col-auto description-title-draft">{{description.label}}</div>
|
<div *ngIf="description.status.internalStatus === descriptionStatusEnum.Draft" class="col-auto description-title-draft">{{description.label}}</div>
|
||||||
|
<div *ngIf="description.status.internalStatus === descriptionStatusEnum.Canceled" class="col-auto description-title-draft">{{description.label}}</div>
|
||||||
|
<div *ngIf="description.status.internalStatus === null" class="col-auto description-title-draft">{{description.label}}</div>
|
||||||
<div class="description-subtitle">
|
<div class="description-subtitle">
|
||||||
<span *ngIf="isUserPlanRelated()" class="col-auto">{{ enumUtils.toPlanUserRolesString(planService.getCurrentUserRolesInPlan(description?.plan?.planUsers)) }}</span>
|
<span *ngIf="isUserPlanRelated()" class="col-auto">{{ enumUtils.toPlanUserRolesString(planService.getCurrentUserRolesInPlan(description?.plan?.planUsers)) }}</span>
|
||||||
<span *ngIf="isUserPlanRelated()">.</span>
|
<span *ngIf="isUserPlanRelated()">.</span>
|
||||||
<span class="col-auto" *ngIf="description.status === descriptionStatusEnum.Finalized && description.plan.accessType === planAccessTypeEnum.Public"><span class="material-icons icon-align">public</span>{{'DESCRIPTION-LISTING.STATES.PUBLIC' | translate}}</span>
|
<span class="col-auto" *ngIf="description.status.internalStatus === descriptionStatusEnum.Finalized && description.plan.accessType === planAccessTypeEnum.Public"><span class="material-icons icon-align">public</span>{{'DESCRIPTION-LISTING.STATES.PUBLIC' | translate}}</span>
|
||||||
<span *ngIf="description.status === descriptionStatusEnum.Finalized && description.plan.accessType != planAccessTypeEnum.Public; else draft" class="col-auto"><span class="material-icons icon-align">done</span>{{ enumUtils.toDescriptionStatusString(description.status) }}</span>
|
<span *ngIf="description.status.internalStatus === descriptionStatusEnum.Finalized && description.plan.accessType != planAccessTypeEnum.Public; else draft" class="col-auto"><span class="material-icons icon-align">done</span>{{ description.status.name }}</span>
|
||||||
<ng-template #draft><span *ngIf="description.status === descriptionStatusEnum.Draft && canEditDescription(); else preview" class=" col-auto draft"><span class="material-icons icon-align">create</span>{{ enumUtils.toDescriptionStatusString(description.status) }}</span></ng-template>
|
<ng-template #draft><span *ngIf="description.status.internalStatus === descriptionStatusEnum.Draft && canEditDescription(); else preview" class=" col-auto draft"><span class="material-icons icon-align">create</span>{{ description.status.name }}</span></ng-template>
|
||||||
<ng-template #preview><span *ngIf="description.status === descriptionStatusEnum.Draft && !canEditDescription()" class=" col-auto draft"><span class="material-icons-outlined mr-1 icon-align">visibility</span>{{ enumUtils.toDescriptionStatusString(description.status) }}</span></ng-template>
|
<ng-template #preview><span *ngIf="description.status.internalStatus === descriptionStatusEnum.Draft && !canEditDescription(); else otherStatus" class=" col-auto draft"><span class="material-icons-outlined mr-1 icon-align">visibility</span>{{ description.status.name }}</span></ng-template>
|
||||||
|
<ng-template #otherStatus><span class=" col-auto draft">{{ description.status.name }}</span></ng-template>
|
||||||
<span>.</span>
|
<span>.</span>
|
||||||
<span class="col">{{'DESCRIPTION-LISTING.GRANT' | translate}}: {{referenceService.getReferencesForTypesFirstSafe(description?.plan?.planReferences, [this.referenceTypeService.getGrantReferenceType()])?.reference?.label}}</span>
|
<span class="col">{{'DESCRIPTION-LISTING.GRANT' | translate}}: {{referenceService.getReferencesForTypesFirstSafe(description?.plan?.planReferences, [this.referenceTypeService.getGrantReferenceType()])?.reference?.label}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -82,7 +82,7 @@ export class DescriptionListingItemComponent extends BaseComponent implements On
|
||||||
this.analyticsService.trackPageView(AnalyticsService.DescriptionListingItem);
|
this.analyticsService.trackPageView(AnalyticsService.DescriptionListingItem);
|
||||||
if (this.description.isActive === IsActive.Inactive) {
|
if (this.description.isActive === IsActive.Inactive) {
|
||||||
this.isDeleted = true;
|
this.isDeleted = true;
|
||||||
} else if (this.description.status === DescriptionStatusEnum.Draft) {
|
} else if (this.description?.status?.internalStatus === DescriptionStatusEnum.Draft) {
|
||||||
this.isDraft = true;
|
this.isDraft = true;
|
||||||
this.isDeleted = false;
|
this.isDeleted = false;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -46,7 +46,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-4 pb-3">
|
<div class="row mb-4 pb-3">
|
||||||
<div class="col-auto pr-0">
|
<div class="col-auto pr-0">
|
||||||
@if(isActive && (canEdit || canAnnotate) && isDraftDescription(description) && !isLocked){
|
@if(isActive && (canEdit || canAnnotate) && isNotFinalizedDescription(description) && !isLocked){
|
||||||
<button (click)="editClicked(description)" mat-mini-fab class="mr-3 actions-btn" matTooltip="{{'DESCRIPTION-OVERVIEW.ACTIONS.EDIT' | translate}}" matTooltipPosition="above">
|
<button (click)="editClicked(description)" mat-mini-fab class="mr-3 actions-btn" matTooltip="{{'DESCRIPTION-OVERVIEW.ACTIONS.EDIT' | translate}}" matTooltipPosition="above">
|
||||||
<mat-icon class="mat-mini-fab-icon">create</mat-icon>
|
<mat-icon class="mat-mini-fab-icon">create</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
|
@ -134,15 +134,19 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<div class="frame mb-3 pt-4 pl-4 pr-5 pb-3">
|
<div class="frame mb-3 pt-4 pl-4 pr-5 pb-3">
|
||||||
<ng-container *ngIf="canFinalize && isDraftDescription(description) && !isLocked">
|
<ng-container *ngIf="availableStatusesTransitions && availableStatusesTransitions.length > 0 && !isLocked">
|
||||||
<div class="row align-items-center" (click)="finalize(description)">
|
<div *ngFor='let status of availableStatusesTransitions'>
|
||||||
|
<div class="row align-items-center" (click)="persistStatus(status, description)">
|
||||||
<div class="col-auto pr-0">
|
<div class="col-auto pr-0">
|
||||||
<button mat-mini-fab class="finalize-btn">
|
<button *ngIf="status.internalStatus === descriptionStatusEnum.Finalized && description.status?.internalStatus != descriptionStatusEnum.Finalized" mat-mini-fab class="finalize-btn">
|
||||||
<mat-icon class="mat-mini-fab-icon check-icon">check</mat-icon>
|
<mat-icon class="mat-mini-fab-icon check-icon">check</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
|
<button *ngIf="description.status?.internalStatus === descriptionStatusEnum.Finalized" mat-mini-fab class="frame-btn">
|
||||||
|
<mat-icon class="mat-mini-fab-icon">unarchive</mat-icon>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-auto pl-0">
|
<div class="col-auto pl-0">
|
||||||
<p class="mb-0 pl-2 frame-txt">{{ 'DESCRIPTION-OVERVIEW.ACTIONS.FINALIZE' | translate }}</p>
|
<p class="mb-0 pl-2 frame-txt">{{ status.name }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row align-items-center">
|
<div class="row align-items-center">
|
||||||
|
@ -150,17 +154,6 @@
|
||||||
<hr class="hr-line">
|
<hr class="hr-line">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ng-container>
|
|
||||||
<ng-container *ngIf="hasReversableStatus(description)">
|
|
||||||
<div class="row mb-3 align-items-center" (click)="reverseFinalization(description)">
|
|
||||||
<div class="col-auto pr-0">
|
|
||||||
<button mat-mini-fab class="frame-btn">
|
|
||||||
<mat-icon class="mat-mini-fab-icon">unarchive</mat-icon>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="col-auto pl-0">
|
|
||||||
<p class="mb-0 mr-0 pl-2 frame-txt">{{ 'DESCRIPTION-OVERVIEW.ACTIONS.REVERSE' | translate }}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container *ngIf="fileTransformerService.availableFormatsFor(fileTransformerEntityTypeEnum.Description).length > 0">
|
<ng-container *ngIf="fileTransformerService.availableFormatsFor(fileTransformerEntityTypeEnum.Description).length > 0">
|
||||||
|
|
|
@ -44,6 +44,8 @@ import { map, takeUntil } from 'rxjs/operators';
|
||||||
import { nameof } from 'ts-simple-nameof';
|
import { nameof } from 'ts-simple-nameof';
|
||||||
import { DescriptionCopyDialogComponent } from '../description-copy-dialog/description-copy-dialog.component';
|
import { DescriptionCopyDialogComponent } from '../description-copy-dialog/description-copy-dialog.component';
|
||||||
import { RouterUtilsService } from '@app/core/services/router/router-utils.service';
|
import { RouterUtilsService } from '@app/core/services/router/router-utils.service';
|
||||||
|
import { DescriptionStatus } from '@app/core/model/description-status/description-status';
|
||||||
|
import { DescriptionStatusService } from '@app/core/services/description-status/description-status.service';
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -73,6 +75,7 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
|
||||||
canFinalize = false;
|
canFinalize = false;
|
||||||
canAnnotate = false;
|
canAnnotate = false;
|
||||||
canInvitePlanUsers = false;
|
canInvitePlanUsers = false;
|
||||||
|
availableStatusesTransitions: DescriptionStatus[];
|
||||||
canAssignPlanUsers(): boolean {
|
canAssignPlanUsers(): boolean {
|
||||||
const authorizationFlags = !this.isPublicView ? (this.description?.plan as Plan)?.authorizationFlags : [];
|
const authorizationFlags = !this.isPublicView ? (this.description?.plan as Plan)?.authorizationFlags : [];
|
||||||
return (authorizationFlags?.some(x => x === AppPermission.AssignPlanUsers) || this.authentication.hasPermission(AppPermission.AssignPlanUsers)) &&
|
return (authorizationFlags?.some(x => x === AppPermission.AssignPlanUsers) || this.authentication.hasPermission(AppPermission.AssignPlanUsers)) &&
|
||||||
|
@ -106,6 +109,7 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
|
||||||
private breadcrumbService: BreadcrumbService,
|
private breadcrumbService: BreadcrumbService,
|
||||||
private httpErrorHandlingService: HttpErrorHandlingService,
|
private httpErrorHandlingService: HttpErrorHandlingService,
|
||||||
private userService: UserService,
|
private userService: UserService,
|
||||||
|
private descriptionStatusService: DescriptionStatusService
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
@ -135,6 +139,7 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
|
||||||
this.breadcrumbService.addIdResolvedValue(data.id.toString(), data.label);
|
this.breadcrumbService.addIdResolvedValue(data.id.toString(), data.label);
|
||||||
|
|
||||||
this.description = data;
|
this.description = data;
|
||||||
|
this.getAvailableStatuses(this.description.id);
|
||||||
this.description.plan.planUsers = this.isActive ? data.plan.planUsers.filter(x => x.isActive === IsActive.Active) : data.plan.planUsers;
|
this.description.plan.planUsers = this.isActive ? data.plan.planUsers.filter(x => x.isActive === IsActive.Active) : data.plan.planUsers;
|
||||||
this.researchers = this.referenceService.getReferencesForTypes(this.description?.plan?.planReferences, [this.referenceTypeService.getResearcherReferenceType()]);
|
this.researchers = this.referenceService.getReferencesForTypes(this.description?.plan?.planReferences, [this.referenceTypeService.getResearcherReferenceType()]);
|
||||||
this.checkLockStatus(this.description.id);
|
this.checkLockStatus(this.description.id);
|
||||||
|
@ -216,6 +221,19 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
|
||||||
return this.language.instant('DESCRIPTION-OVERVIEW.INFOS.UNAUTHORIZED-ORCID');
|
return this.language.instant('DESCRIPTION-OVERVIEW.INFOS.UNAUTHORIZED-ORCID');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getAvailableStatuses(id: Guid){
|
||||||
|
this.descriptionStatusService.getAvailableTransitions(id).pipe(takeUntil(this._destroyed))
|
||||||
|
.subscribe(
|
||||||
|
(statuses) => {
|
||||||
|
this.availableStatusesTransitions = statuses;
|
||||||
|
},
|
||||||
|
(error) => this.httpErrorHandlingService.handleBackedRequestError(error)
|
||||||
|
); }
|
||||||
|
|
||||||
|
hasAvailableFinalizeStatus() {
|
||||||
|
return this.availableStatusesTransitions?.find(x => x.internalStatus === DescriptionStatusEnum.Finalized) != null;
|
||||||
|
}
|
||||||
|
|
||||||
checkLockStatus(id: Guid) {
|
checkLockStatus(id: Guid) {
|
||||||
this.lockService.checkLockStatus(id).pipe(takeUntil(this._destroyed))
|
this.lockService.checkLockStatus(id).pipe(takeUntil(this._destroyed))
|
||||||
.subscribe({
|
.subscribe({
|
||||||
|
@ -290,8 +308,8 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
|
||||||
return this.authentication.currentAccountIsAuthenticated();
|
return this.authentication.currentAccountIsAuthenticated();
|
||||||
}
|
}
|
||||||
|
|
||||||
isDraftDescription(description: Description) {
|
isNotFinalizedDescription(description: Description) {
|
||||||
return description.status == DescriptionStatusEnum.Draft;
|
return description?.status?.internalStatus != DescriptionStatusEnum.Finalized;
|
||||||
}
|
}
|
||||||
|
|
||||||
editClicked(description: Description) {
|
editClicked(description: Description) {
|
||||||
|
@ -426,7 +444,30 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
finalize(description: Description) {
|
persistStatus(status: DescriptionStatus, description: Description) {
|
||||||
|
if (status.internalStatus != null && status.internalStatus === DescriptionStatusEnum.Finalized) {
|
||||||
|
this.finalize(description, status.id);
|
||||||
|
} else if (status.internalStatus != null && description.status.internalStatus === DescriptionStatusEnum.Finalized){
|
||||||
|
this.reverseFinalization(description, status.id);
|
||||||
|
} else {
|
||||||
|
// other statuses
|
||||||
|
const descriptionStatusPersist: DescriptionStatusPersist = {
|
||||||
|
id: description.id,
|
||||||
|
statusId: status.id,
|
||||||
|
hash: description.hash
|
||||||
|
};
|
||||||
|
this.descriptionService.persistStatus(descriptionStatusPersist).pipe(takeUntil(this._destroyed))
|
||||||
|
.subscribe({
|
||||||
|
next: () => {
|
||||||
|
this.reloadPage();
|
||||||
|
this.onUpdateCallbackSuccess()
|
||||||
|
},
|
||||||
|
error: (error: any) => this.onUpdateCallbackError(error)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
finalize(description: Description, statusId: Guid) {
|
||||||
|
|
||||||
this.descriptionService.validate([description.id]).pipe(takeUntil(this._destroyed))
|
this.descriptionService.validate([description.id]).pipe(takeUntil(this._destroyed))
|
||||||
.subscribe({
|
.subscribe({
|
||||||
|
@ -448,7 +489,7 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
|
||||||
if (result) {
|
if (result) {
|
||||||
const descriptionStatusPersist: DescriptionStatusPersist = {
|
const descriptionStatusPersist: DescriptionStatusPersist = {
|
||||||
id: description.id,
|
id: description.id,
|
||||||
status: DescriptionStatusEnum.Finalized,
|
statusId: statusId,
|
||||||
hash: description.hash
|
hash: description.hash
|
||||||
};
|
};
|
||||||
this.descriptionService.persistStatus(descriptionStatusPersist).pipe(takeUntil(this._destroyed))
|
this.descriptionService.persistStatus(descriptionStatusPersist).pipe(takeUntil(this._destroyed))
|
||||||
|
@ -472,10 +513,10 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
|
||||||
}
|
}
|
||||||
|
|
||||||
hasReversableStatus(description: Description): boolean {
|
hasReversableStatus(description: Description): boolean {
|
||||||
return description.plan.status == PlanStatusEnum.Draft && description.status == DescriptionStatusEnum.Finalized && this.canFinalize
|
return description.plan.status == PlanStatusEnum.Draft && description?.status?.internalStatus == DescriptionStatusEnum.Finalized && this.canFinalize && this.availableStatusesTransitions?.find(x => x.internalStatus === DescriptionStatusEnum.Draft) != null
|
||||||
}
|
}
|
||||||
|
|
||||||
reverseFinalization(description: Description) {
|
reverseFinalization(description: Description, statusId: Guid) {
|
||||||
const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
|
const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
|
||||||
restoreFocus: false,
|
restoreFocus: false,
|
||||||
data: {
|
data: {
|
||||||
|
@ -489,7 +530,7 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
|
||||||
if (result) {
|
if (result) {
|
||||||
const planUserRemovePersist: DescriptionStatusPersist = {
|
const planUserRemovePersist: DescriptionStatusPersist = {
|
||||||
id: description.id,
|
id: description.id,
|
||||||
status: DescriptionStatusEnum.Draft,
|
statusId: statusId,
|
||||||
hash: description.hash
|
hash: description.hash
|
||||||
};
|
};
|
||||||
this.descriptionService.persistStatus(planUserRemovePersist).pipe(takeUntil(this._destroyed))
|
this.descriptionService.persistStatus(planUserRemovePersist).pipe(takeUntil(this._destroyed))
|
||||||
|
@ -512,7 +553,9 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
|
||||||
nameof<Description>(x => x.id),
|
nameof<Description>(x => x.id),
|
||||||
nameof<Description>(x => x.label),
|
nameof<Description>(x => x.label),
|
||||||
nameof<Description>(x => x.description),
|
nameof<Description>(x => x.description),
|
||||||
nameof<Description>(x => x.status),
|
[nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.id)].join('.'),
|
||||||
|
[nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.name)].join('.'),
|
||||||
|
[nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.internalStatus)].join('.'),
|
||||||
nameof<Description>(x => x.updatedAt),
|
nameof<Description>(x => x.updatedAt),
|
||||||
nameof<Description>(x => x.belongsToCurrentTenant),
|
nameof<Description>(x => x.belongsToCurrentTenant),
|
||||||
nameof<Description>(x => x.hash),
|
nameof<Description>(x => x.hash),
|
||||||
|
|
|
@ -44,6 +44,7 @@ import { PlanFilterDialogComponent } from './filtering/plan-filter-dialog/plan-f
|
||||||
import { PlanListingFilters } from './filtering/plan-filter.component';
|
import { PlanListingFilters } from './filtering/plan-filter.component';
|
||||||
import { Lookup } from '@common/model/lookup';
|
import { Lookup } from '@common/model/lookup';
|
||||||
import { MatSelectChange } from '@angular/material/select';
|
import { MatSelectChange } from '@angular/material/select';
|
||||||
|
import { DescriptionStatus } from '@app/core/model/description-status/description-status';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-plan-listing-component',
|
selector: 'app-plan-listing-component',
|
||||||
|
@ -513,10 +514,11 @@ export class PlanListingComponent extends BaseListingComponent<BasePlan, PlanLoo
|
||||||
|
|
||||||
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.id)].join('.'),
|
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.id)].join('.'),
|
||||||
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.label)].join('.'),
|
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.label)].join('.'),
|
||||||
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.status)].join('.'),
|
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.id)].join('.'),
|
||||||
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.descriptionTemplate), nameof<DescriptionTemplate>(x => x.groupId)].join('.'),
|
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.name)].join('.'),
|
||||||
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.planDescriptionTemplate), nameof<PlanDescriptionTemplate>(x => x.sectionId)].join('.'),
|
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.internalStatus)].join('.'), [nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.descriptionTemplate), nameof<DescriptionTemplate>(x => x.groupId)].join('.'),
|
||||||
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.isActive)].join('.'),
|
[nameof<Plan>(x => x.descriptions), nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.planDescriptionTemplate), nameof<PlanDescriptionTemplate>(x => x.sectionId)].join('.'),
|
||||||
|
[nameof<Plan>(x => x.descriptions), nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.isActive)].join('.'),
|
||||||
|
|
||||||
[nameof<Plan>(x => x.blueprint), nameof<PlanBlueprint>(x => x.id)].join('.'),
|
[nameof<Plan>(x => x.blueprint), nameof<PlanBlueprint>(x => x.id)].join('.'),
|
||||||
[nameof<Plan>(x => x.blueprint), nameof<PlanBlueprint>(x => x.label)].join('.'),
|
[nameof<Plan>(x => x.blueprint), nameof<PlanBlueprint>(x => x.label)].join('.'),
|
||||||
|
|
|
@ -50,6 +50,7 @@ import { PlanFinalizeDialogComponent, PlanFinalizeDialogOutput } from '../plan-f
|
||||||
import { PlanInvitationDialogComponent } from '../invitation/dialog/plan-invitation-dialog.component';
|
import { PlanInvitationDialogComponent } from '../invitation/dialog/plan-invitation-dialog.component';
|
||||||
import { NewVersionPlanDialogComponent } from '../new-version-dialog/plan-new-version-dialog.component';
|
import { NewVersionPlanDialogComponent } from '../new-version-dialog/plan-new-version-dialog.component';
|
||||||
import { RouterUtilsService } from '@app/core/services/router/router-utils.service';
|
import { RouterUtilsService } from '@app/core/services/router/router-utils.service';
|
||||||
|
import { DescriptionStatus } from '@app/core/model/description-status/description-status';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-plan-overview',
|
selector: 'app-plan-overview',
|
||||||
|
@ -133,9 +134,9 @@ export class PlanOverviewComponent extends BaseComponent implements OnInit {
|
||||||
this.plan.otherPlanVersions = data.otherPlanVersions?.filter(x => x.isActive === IsActive.Active) || null;
|
this.plan.otherPlanVersions = data.otherPlanVersions?.filter(x => x.isActive === IsActive.Active) || null;
|
||||||
if (this.plan.descriptions) {
|
if (this.plan.descriptions) {
|
||||||
if (this.plan.status == PlanStatusEnum.Finalized) {
|
if (this.plan.status == PlanStatusEnum.Finalized) {
|
||||||
this.plan.descriptions = data.descriptions.filter(x => x.isActive === IsActive.Active && x.status === DescriptionStatusEnum.Finalized);
|
this.plan.descriptions = data.descriptions.filter(x => x.isActive === IsActive.Active && x.status?.internalStatus === DescriptionStatusEnum.Finalized);
|
||||||
} else {
|
} else {
|
||||||
this.plan.descriptions = data.descriptions.filter(x => x.isActive === IsActive.Active && x.status !== DescriptionStatusEnum.Canceled);
|
this.plan.descriptions = data.descriptions.filter(x => x.isActive === IsActive.Active && x.status?.internalStatus !== DescriptionStatusEnum.Canceled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (data.entityDois && data.entityDois.length > 0) this.plan.entityDois = data.entityDois.filter(x => x.isActive === IsActive.Active);
|
if (data.entityDois && data.entityDois.length > 0) this.plan.entityDois = data.entityDois.filter(x => x.isActive === IsActive.Active);
|
||||||
|
@ -660,7 +661,9 @@ export class PlanOverviewComponent extends BaseComponent implements OnInit {
|
||||||
[nameof<Plan>(x => x.entityDois), nameof<EntityDoi>(x => x.isActive)].join('.'),
|
[nameof<Plan>(x => x.entityDois), nameof<EntityDoi>(x => x.isActive)].join('.'),
|
||||||
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.id)].join('.'),
|
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.id)].join('.'),
|
||||||
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.label)].join('.'),
|
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.label)].join('.'),
|
||||||
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.status)].join('.'),
|
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.id)].join('.'),
|
||||||
|
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.name)].join('.'),
|
||||||
|
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.internalStatus)].join('.'),
|
||||||
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.isActive)].join('.'),
|
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.isActive)].join('.'),
|
||||||
[nameof<Plan>(x => x.planUsers), nameof<PlanUser>(x => x.id)].join('.'),
|
[nameof<Plan>(x => x.planUsers), nameof<PlanUser>(x => x.id)].join('.'),
|
||||||
[nameof<Plan>(x => x.planUsers), nameof<PlanUser>(x => x.sectionId)].join('.'),
|
[nameof<Plan>(x => x.planUsers), nameof<PlanUser>(x => x.sectionId)].join('.'),
|
||||||
|
|
|
@ -263,9 +263,9 @@ export class PlanEditorComponent extends BaseEditor<PlanEditorModel, Plan> imple
|
||||||
if (data) {
|
if (data) {
|
||||||
if (data.descriptions) {
|
if (data.descriptions) {
|
||||||
if (data.status == PlanStatusEnum.Finalized) {
|
if (data.status == PlanStatusEnum.Finalized) {
|
||||||
data.descriptions = data.descriptions.filter(x => x.isActive === IsActive.Active && x.status === DescriptionStatusEnum.Finalized);
|
data.descriptions = data.descriptions.filter(x => x.isActive === IsActive.Active && x.status.internalStatus === DescriptionStatusEnum.Finalized);
|
||||||
} else {
|
} else {
|
||||||
data.descriptions = data.descriptions.filter(x => x.isActive === IsActive.Active && x.status !== DescriptionStatusEnum.Canceled);
|
data.descriptions = data.descriptions.filter(x => x.isActive === IsActive.Active && x.status.internalStatus !== DescriptionStatusEnum.Canceled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (data.planDescriptionTemplates) {
|
if (data.planDescriptionTemplates) {
|
||||||
|
|
|
@ -15,6 +15,7 @@ import { Guid } from '@common/types/guid';
|
||||||
import { takeUntil, tap } from 'rxjs/operators';
|
import { takeUntil, tap } from 'rxjs/operators';
|
||||||
import { nameof } from 'ts-simple-nameof';
|
import { nameof } from 'ts-simple-nameof';
|
||||||
import { EntityDoi } from '@app/core/model/entity-doi/entity-doi';
|
import { EntityDoi } from '@app/core/model/entity-doi/entity-doi';
|
||||||
|
import { DescriptionStatus } from '@app/core/model/description-status/description-status';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class PlanEditorEntityResolver extends BaseEditorResolver {
|
export class PlanEditorEntityResolver extends BaseEditorResolver {
|
||||||
|
@ -56,7 +57,9 @@ export class PlanEditorEntityResolver extends BaseEditorResolver {
|
||||||
|
|
||||||
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.id)].join('.'),
|
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.id)].join('.'),
|
||||||
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.label)].join('.'),
|
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.label)].join('.'),
|
||||||
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.status)].join('.'),
|
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.id)].join('.'),
|
||||||
|
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.name)].join('.'),
|
||||||
|
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.internalStatus)].join('.'),
|
||||||
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.isActive)].join('.'),
|
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.isActive)].join('.'),
|
||||||
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.planDescriptionTemplate), nameof<PlanDescriptionTemplate>(x => x.id)].join('.'),
|
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.planDescriptionTemplate), nameof<PlanDescriptionTemplate>(x => x.id)].join('.'),
|
||||||
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.planDescriptionTemplate), nameof<PlanDescriptionTemplate>(x => x.sectionId)].join('.'),
|
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.planDescriptionTemplate), nameof<PlanDescriptionTemplate>(x => x.sectionId)].join('.'),
|
||||||
|
|
|
@ -30,10 +30,10 @@
|
||||||
</mat-expansion-panel-header>
|
</mat-expansion-panel-header>
|
||||||
<div *ngIf="plan.descriptions && plan.descriptions.length > 0">
|
<div *ngIf="plan.descriptions && plan.descriptions.length > 0">
|
||||||
<div *ngFor="let description of plan.descriptions" class="row pl-3 descriptions">
|
<div *ngFor="let description of plan.descriptions" class="row pl-3 descriptions">
|
||||||
<mat-icon *ngIf="description.status == descriptionStatusEnum.Draft" class="col-1 draft-bookmark">bookmark</mat-icon>
|
<mat-icon *ngIf="description?.status?.internalStatus == descriptionStatusEnum.Draft" class="col-1 draft-bookmark">bookmark</mat-icon>
|
||||||
<mat-icon *ngIf="description.status == descriptionStatusEnum.Finalized" class="col-1 finalized-bookmark">bookmark</mat-icon>
|
<mat-icon *ngIf="description?.status?.internalStatus == descriptionStatusEnum.Finalized" class="col-1 finalized-bookmark">bookmark</mat-icon>
|
||||||
<h4 *ngIf="description.status == descriptionStatusEnum.Draft" class="col-11 ml-auto mt-1 mb-4">
|
<h4 *ngIf="description.status?.internalStatus == descriptionStatusEnum.Draft" class="col-11 ml-auto mt-1 mb-4">
|
||||||
<span>{{ 'TYPES.DESCRIPTION-STATUS.DRAFT' | translate }}
|
<span>{{ description?.status?.name}}
|
||||||
<ng-container *ngIf="!isDescriptionValid(description.id)">
|
<ng-container *ngIf="!isDescriptionValid(description.id)">
|
||||||
({{'PLAN-FINALISE-DIALOG.INVALID' | translate}})
|
({{'PLAN-FINALISE-DIALOG.INVALID' | translate}})
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
@ -41,7 +41,7 @@
|
||||||
{{ description.label }}
|
{{ description.label }}
|
||||||
<i *ngIf="(descriptionValidationOutputMap.get(description.id) != descriptionValidationOutputEnum.Invalid) && (descriptionValidationOutputMap.get(description.id) != descriptionValidationOutputEnum.Valid)" class="fa fa-spinner fa-spin" ></i>
|
<i *ngIf="(descriptionValidationOutputMap.get(description.id) != descriptionValidationOutputEnum.Invalid) && (descriptionValidationOutputMap.get(description.id) != descriptionValidationOutputEnum.Valid)" class="fa fa-spinner fa-spin" ></i>
|
||||||
</h4>
|
</h4>
|
||||||
<h4 *ngIf="description.status == descriptionStatusEnum.Finalized" class="col-11 ml-auto mt-1 mb-4">{{ description.label }}</h4>
|
<h4 *ngIf="description.status.internalStatus == descriptionStatusEnum.Finalized" class="col-11 ml-auto mt-1 mb-4">{{ description.label }}</h4>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="!plan.descriptions" class="emptyList">{{ 'PLAN-FINALISE-DIALOG.EMPTY' | translate }} </div>
|
<div *ngIf="!plan.descriptions" class="emptyList">{{ 'PLAN-FINALISE-DIALOG.EMPTY' | translate }} </div>
|
||||||
|
|
|
@ -74,7 +74,7 @@ export class PlanFinalizeDialogComponent extends BaseComponent implements OnInit
|
||||||
|
|
||||||
getFinalizedDescriptions() {
|
getFinalizedDescriptions() {
|
||||||
if (!this.plan.descriptions) return [];
|
if (!this.plan.descriptions) return [];
|
||||||
const finalizedDescriptions = this.plan.descriptions.filter(x => x.status === DescriptionStatusEnum.Finalized);
|
const finalizedDescriptions = this.plan.descriptions.filter(x => x.status.internalStatus === DescriptionStatusEnum.Finalized);
|
||||||
if (finalizedDescriptions?.length > 0){
|
if (finalizedDescriptions?.length > 0){
|
||||||
finalizedDescriptions.forEach(finalize => {
|
finalizedDescriptions.forEach(finalize => {
|
||||||
this.descriptionValidationOutputMap.set(finalize.id, DescriptionValidationOutput.Valid);
|
this.descriptionValidationOutputMap.set(finalize.id, DescriptionValidationOutput.Valid);
|
||||||
|
@ -88,16 +88,16 @@ export class PlanFinalizeDialogComponent extends BaseComponent implements OnInit
|
||||||
}
|
}
|
||||||
|
|
||||||
validateDescriptions(plan: Plan) {
|
validateDescriptions(plan: Plan) {
|
||||||
if (!plan.descriptions?.some(x => x.status == DescriptionStatusEnum.Draft)) return;
|
if (!plan.descriptions?.some(x => x.status.internalStatus == DescriptionStatusEnum.Draft)) return;
|
||||||
|
|
||||||
const draftDescriptions = this.plan.descriptions.filter(x => x.status == DescriptionStatusEnum.Draft) || [];
|
const draftDescriptions = this.plan.descriptions.filter(x => x.status.internalStatus == DescriptionStatusEnum.Draft) || [];
|
||||||
if ( draftDescriptions.length > 0){
|
if ( draftDescriptions.length > 0){
|
||||||
draftDescriptions.forEach(draft => {
|
draftDescriptions.forEach(draft => {
|
||||||
this.descriptionValidationOutputMap.set(draft.id, DescriptionValidationOutput.Pending);
|
this.descriptionValidationOutputMap.set(draft.id, DescriptionValidationOutput.Pending);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.descriptionService.validate(plan.descriptions.filter(x => x.status == DescriptionStatusEnum.Draft).map(x => x.id)).pipe(takeUntil(this._destroyed),)
|
this.descriptionService.validate(plan.descriptions.filter(x => x.status.internalStatus == DescriptionStatusEnum.Draft).map(x => x.id)).pipe(takeUntil(this._destroyed),)
|
||||||
.subscribe(result => {
|
.subscribe(result => {
|
||||||
this.validationResults = result;
|
this.validationResults = result;
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue