From dc2c3d15c7e38018cbca80bb47ab2db9c229a6d4 Mon Sep 17 00:00:00 2001
From: Lars Johansson <lars.johansson@ess.eu>
Date: Mon, 2 Jan 2023 20:23:18 +0100
Subject: [PATCH] Refactor approve structures for approve create

---
 .../repository/IDeviceGroupRepository.java    |  3 ++
 .../repository/IDeviceTypeRepository.java     |  3 ++
 .../repository/IDisciplineRepository.java     |  3 ++
 .../names/repository/INameRepository.java     | 52 +++++++++++++++++++
 .../repository/ISubsystemRepository.java      |  3 ++
 .../repository/ISystemGroupRepository.java    |  3 ++
 .../names/repository/ISystemRepository.java   |  3 ++
 .../names/service/DeviceGroupService.java     | 27 +++++++++-
 .../names/service/DeviceTypeService.java      | 27 +++++++++-
 .../names/service/DisciplineService.java      | 27 +++++++++-
 .../openepics/names/service/NamesService.java |  2 +
 .../names/service/StructuresService.java      | 12 ++++-
 .../names/service/SubsystemService.java       | 45 +++++++++++-----
 .../names/service/SystemGroupService.java     | 46 +++++++++++-----
 .../names/service/SystemService.java          | 46 +++++++++++-----
 .../openepics/names/util/StructureUtil.java   | 19 +++++++
 16 files changed, 281 insertions(+), 40 deletions(-)

diff --git a/src/main/java/org/openepics/names/repository/IDeviceGroupRepository.java b/src/main/java/org/openepics/names/repository/IDeviceGroupRepository.java
index 703f3e3b..57384ae8 100644
--- a/src/main/java/org/openepics/names/repository/IDeviceGroupRepository.java
+++ b/src/main/java/org/openepics/names/repository/IDeviceGroupRepository.java
@@ -60,4 +60,7 @@ public interface IDeviceGroupRepository extends JpaRepository<DeviceGroup, Long>
     @Query("FROM DeviceGroup dg WHERE dg.latest = true AND dg.deleted = false AND dg.parentUuid = ?1")
     List<DeviceGroup> findLatestNotDeletedByParent(String uuid);
 
+    @Query("FROM DeviceGroup dg WHERE dg.uuid = ?1 AND dg.id < ?2 ORDER BY dg.id DESC")
+    List<DeviceGroup> findPreviousByUuidAndId(String uuid, Long id);
+
 }
diff --git a/src/main/java/org/openepics/names/repository/IDeviceTypeRepository.java b/src/main/java/org/openepics/names/repository/IDeviceTypeRepository.java
index b2559d4e..1b641d28 100644
--- a/src/main/java/org/openepics/names/repository/IDeviceTypeRepository.java
+++ b/src/main/java/org/openepics/names/repository/IDeviceTypeRepository.java
@@ -60,4 +60,7 @@ public interface IDeviceTypeRepository extends JpaRepository<DeviceType, Long> {
     @Query("FROM DeviceType dt WHERE dt.latest = true AND dt.deleted = false AND dt.parentUuid = ?1")
     List<DeviceType> findLatestNotDeletedByParent(String uuid);
 
+    @Query("FROM DeviceType dt WHERE dt.uuid = ?1 AND dt.id < ?2 ORDER BY dt.id DESC")
+    List<DeviceType> findPreviousByUuidAndId(String uuid, Long id);
+
 }
diff --git a/src/main/java/org/openepics/names/repository/IDisciplineRepository.java b/src/main/java/org/openepics/names/repository/IDisciplineRepository.java
index 835cd4ac..2338f83c 100644
--- a/src/main/java/org/openepics/names/repository/IDisciplineRepository.java
+++ b/src/main/java/org/openepics/names/repository/IDisciplineRepository.java
@@ -54,4 +54,7 @@ public interface IDisciplineRepository extends JpaRepository<Discipline, Long> {
     @Query("FROM Discipline di WHERE di.latest = true AND di.deleted = false")
     List<Discipline> findLatestNotDeleted();
 
+    @Query("FROM Discipline di WHERE di.uuid = ?1 AND di.id < ?2 ORDER BY di.id DESC")
+    List<Discipline> findPreviousByUuidAndId(String uuid, Long id);
+
 }
diff --git a/src/main/java/org/openepics/names/repository/INameRepository.java b/src/main/java/org/openepics/names/repository/INameRepository.java
index 3bb4025a..1568efd3 100644
--- a/src/main/java/org/openepics/names/repository/INameRepository.java
+++ b/src/main/java/org/openepics/names/repository/INameRepository.java
@@ -18,6 +18,7 @@
 
 package org.openepics.names.repository;
 
+import java.util.Date;
 import java.util.List;
 
 import org.openepics.names.repository.model.Name;
@@ -48,6 +49,13 @@ public interface INameRepository extends JpaRepository<Name, Long> {
     @Query("FROM Name n WHERE n.latest = true AND n.deleted = false")
     List<Name> findLatestNotDeleted();
 
+    @Query("SELECT n FROM Name n, SystemGroup sg "
+            + "WHERE n.latest = true "
+            + "AND sg.uuid = n.systemgroupUuid "
+            + "AND sg.latest = true "
+            + "AND sg.uuid = ?1")
+    List<Name> findLatestBySystemGroupUuid(String uuid);
+
     @Query("SELECT n FROM Name n, SystemGroup sg "
             + "WHERE n.latest = true "
             + "AND sg.uuid = n.systemgroupUuid "
@@ -55,6 +63,13 @@ public interface INameRepository extends JpaRepository<Name, Long> {
             + "AND sg.mnemonic = ?1")
     List<Name> findLatestBySystemGroupMnemonic(String mnemonic);
 
+    @Query("SELECT n FROM Name n, System sys "
+            + "WHERE n.latest = true "
+            + "AND sys.uuid = n.systemUuid "
+            + "AND sys.latest = true "
+            + "AND sys.uuid = ?1")
+    List<Name> findLatestBySystemUuid(String uuid);
+
     @Query("SELECT n FROM Name n, System sys "
             + "WHERE n.latest = true "
             + "AND sys.uuid = n.systemUuid "
@@ -62,6 +77,15 @@ public interface INameRepository extends JpaRepository<Name, Long> {
             + "AND sys.mnemonic = ?1")
     List<Name> findLatestBySystemMnemonic(String mnemonic);
 
+    @Query("SELECT n FROM Name n, Subsystem sub, System sys "
+            + "WHERE n.latest = true "
+            + "AND sub.uuid = n.subsystemUuid "
+            + "AND sub.latest = true "
+            + "AND sys.uuid = sub.parentUuid  "
+            + "AND sys.latest = true "
+            + "AND sys.uuid = ?1")
+    List<Name> findLatestBySystemUuidThroughSubsystem(String uuid);
+
     @Query("SELECT n FROM Name n, Subsystem sub, System sys "
             + "WHERE n.latest = true "
             + "AND sub.uuid = n.subsystemUuid "
@@ -71,6 +95,13 @@ public interface INameRepository extends JpaRepository<Name, Long> {
             + "AND sys.mnemonic = ?1")
     List<Name> findLatestBySystemMnemonicThroughSubsystem(String mnemonic);
 
+    @Query("SELECT n FROM Name n, Subsystem sub "
+            + "WHERE n.latest = true "
+            + "AND sub.uuid = n.subsystemUuid "
+            + "AND sub.latest = true "
+            + "AND sub.uuid = ?1")
+    List<Name> findLatestBySubsystemUuid(String uuid);
+
     @Query("SELECT n FROM Name n, Subsystem sub "
             + "WHERE n.latest = true "
             + "AND sub.uuid = n.subsystemUuid "
@@ -78,6 +109,17 @@ public interface INameRepository extends JpaRepository<Name, Long> {
             + "AND sub.mnemonic = ?1")
     List<Name> findLatestBySubsystemMnemonic(String mnemonic);
 
+    @Query("SELECT n FROM Name n, DeviceType dt, DeviceGroup dg, Discipline di "
+            + "WHERE n.latest = true "
+            + "AND dt.uuid = n.devicetypeUuid "
+            + "AND dt.latest = true "
+            + "AND dg.uuid = dt.parentUuid "
+            + "AND dg.latest = true "
+            + "AND di.uuid = dg.parentUuid "
+            + "AND di.latest = true "
+            + "AND di.uuid = ?1")
+    List<Name> findLatestByDisciplineUuid(String uuid);
+
     @Query("SELECT n FROM Name n, DeviceType dt, DeviceGroup dg, Discipline di "
             + "WHERE n.latest = true "
             + "AND dt.uuid = n.devicetypeUuid "
@@ -89,6 +131,13 @@ public interface INameRepository extends JpaRepository<Name, Long> {
             + "AND di.mnemonic = ?1")
     List<Name> findLatestByDisciplineMnemonic(String mnemonic);
 
+    @Query("SELECT n FROM Name n, DeviceType dt "
+            + "WHERE n.latest = true "
+            + "AND dt.uuid = n.devicetypeUuid "
+            + "AND dt.latest = true "
+            + "AND dt.uuid = ?1")
+    List<Name> findLatestByDeviceTypeUuid(String uuid);
+
     @Query("SELECT n FROM Name n, DeviceType dt "
             + "WHERE n.latest = true "
             + "AND dt.uuid = n.devicetypeUuid "
@@ -96,4 +145,7 @@ public interface INameRepository extends JpaRepository<Name, Long> {
             + "AND dt.mnemonic = ?1")
     List<Name> findLatestByDeviceTypeMnemonic(String mnemonic);
 
+    @Query("FROM Name n WHERE n.requested >= ?1 AND n.requested <= ?2")
+    List<Name> findByRequestedBetween(Date from, Date to);
+
 }
diff --git a/src/main/java/org/openepics/names/repository/ISubsystemRepository.java b/src/main/java/org/openepics/names/repository/ISubsystemRepository.java
index a60e894b..d0f5f6a5 100644
--- a/src/main/java/org/openepics/names/repository/ISubsystemRepository.java
+++ b/src/main/java/org/openepics/names/repository/ISubsystemRepository.java
@@ -60,4 +60,7 @@ public interface ISubsystemRepository extends JpaRepository<Subsystem, Long> {
     @Query("FROM Subsystem sub WHERE sub.latest = true AND sub.deleted = false AND sub.parentUuid = ?1")
     List<Subsystem> findLatestNotDeletedByParent(String uuid);
 
+    @Query("FROM Subsystem sub WHERE sub.uuid = ?1 AND sub.id < ?2 ORDER BY sub.id DESC")
+    List<Subsystem> findPreviousByUuidAndId(String uuid, Long id);
+
 }
diff --git a/src/main/java/org/openepics/names/repository/ISystemGroupRepository.java b/src/main/java/org/openepics/names/repository/ISystemGroupRepository.java
index f8c5d60b..1d380032 100644
--- a/src/main/java/org/openepics/names/repository/ISystemGroupRepository.java
+++ b/src/main/java/org/openepics/names/repository/ISystemGroupRepository.java
@@ -54,4 +54,7 @@ public interface ISystemGroupRepository extends JpaRepository<SystemGroup, Long>
     @Query("FROM SystemGroup sg WHERE sg.latest = true AND sg.deleted = false")
     List<SystemGroup> findLatestNotDeleted();
 
+    @Query("FROM SystemGroup sg WHERE sg.uuid = ?1 AND sg.id < ?2 ORDER BY sg.id DESC")
+    List<SystemGroup> findPreviousByUuidAndId(String uuid, Long id);
+
 }
diff --git a/src/main/java/org/openepics/names/repository/ISystemRepository.java b/src/main/java/org/openepics/names/repository/ISystemRepository.java
index 4c0e96c8..d066b3e8 100644
--- a/src/main/java/org/openepics/names/repository/ISystemRepository.java
+++ b/src/main/java/org/openepics/names/repository/ISystemRepository.java
@@ -60,4 +60,7 @@ public interface ISystemRepository extends JpaRepository<System, Long> {
     @Query("FROM System sys WHERE sys.latest = true AND sys.deleted = false AND sys.parentUuid = ?1")
     List<System> findLatestNotDeletedByParent(String uuid);
 
+    @Query("FROM System sys WHERE sys.uuid = ?1 AND sys.id < ?2 ORDER BY sys.id DESC")
+    List<System> findPreviousByUuidAndId(String uuid, Long id);
+
 }
diff --git a/src/main/java/org/openepics/names/service/DeviceGroupService.java b/src/main/java/org/openepics/names/service/DeviceGroupService.java
index d3b22727..3281ef28 100644
--- a/src/main/java/org/openepics/names/service/DeviceGroupService.java
+++ b/src/main/java/org/openepics/names/service/DeviceGroupService.java
@@ -24,13 +24,16 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import org.openepics.names.repository.DeviceGroupRepository;
+import org.openepics.names.repository.IDeviceGroupRepository;
 import org.openepics.names.repository.model.DeviceGroup;
 import org.openepics.names.rest.beans.Status;
 import org.openepics.names.rest.beans.element.StructureElement;
 import org.openepics.names.rest.beans.element.StructureElementCommand;
 import org.openepics.names.util.HolderSystemDeviceStructure;
 import org.openepics.names.util.StructureChoice;
+import org.openepics.names.util.StructureCommand;
 import org.openepics.names.util.StructureElementUtil;
+import org.openepics.names.util.StructureUtil;
 import org.openepics.names.util.ValidateUtil;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -45,13 +48,21 @@ import org.springframework.transaction.annotation.Transactional;
 @Service
 public class DeviceGroupService {
 
+    // note
+    //     structurecommand
+    //         cud - create update delete
+    //         acr - approve cancel reject
+
     private static final Logger LOGGER = Logger.getLogger(DeviceGroupService.class.getName());
 
+    private IDeviceGroupRepository iDeviceGroupRepository;
     private DeviceGroupRepository deviceGroupRepository;
 
     @Autowired
     public DeviceGroupService(
+            IDeviceGroupRepository iDeviceGroupRepository,
             DeviceGroupRepository deviceGroupRepository) {
+        this.iDeviceGroupRepository = iDeviceGroupRepository;
         this.deviceGroupRepository = deviceGroupRepository;
     }
 
@@ -67,7 +78,14 @@ public class DeviceGroupService {
         //         find
         //         approve - update structure to status APPROVED, latest to true
         //         possibly validate that approved
-        //         automatically create name when system structure is approved
+        //         additional
+        //             find out previous to find out what is approved - create update delete
+        //             approve create
+        //                 automatically create name when system structure is approved
+        //                 condition on name and structure entry
+        //                     system structure should exist (uuid), one entry that is not deleted
+        //                     name should not exist (system structure mnemonic)
+        //                 within current transaction
         //     return
         //         structure element for approved structure
 
@@ -97,6 +115,13 @@ public class DeviceGroupService {
         deviceGroup.setLatest(Boolean.TRUE);
         deviceGroupRepository.updateDeviceGroup(deviceGroup);
 
+        // additional
+        // find out previous
+        List<DeviceGroup> previouses = iDeviceGroupRepository.findPreviousByUuidAndId(uuid, deviceGroup.getId());
+        StructureCommand structureCommandCUD = StructureUtil.getStructureCommandCUD(previouses, deviceGroup);
+        DeviceGroup previous = previouses != null && !previouses.isEmpty() ? previouses.get(0) : null;
+        LOGGER.log(Level.FINE, "approveStructure, structureCommandCUD:        {0}", structureCommandCUD);
+
         LOGGER.log(Level.FINE, "approveStructure, structureElement:           {0}", structureElement);
         return StructureElementUtil.getStructureElementProcessed(deviceGroup, holder, StructureChoice.STRUCTURE);
     }
diff --git a/src/main/java/org/openepics/names/service/DeviceTypeService.java b/src/main/java/org/openepics/names/service/DeviceTypeService.java
index 7f12429c..e90de7fd 100644
--- a/src/main/java/org/openepics/names/service/DeviceTypeService.java
+++ b/src/main/java/org/openepics/names/service/DeviceTypeService.java
@@ -24,13 +24,16 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import org.openepics.names.repository.DeviceTypeRepository;
+import org.openepics.names.repository.IDeviceTypeRepository;
 import org.openepics.names.repository.model.DeviceType;
 import org.openepics.names.rest.beans.Status;
 import org.openepics.names.rest.beans.element.StructureElement;
 import org.openepics.names.rest.beans.element.StructureElementCommand;
 import org.openepics.names.util.HolderSystemDeviceStructure;
 import org.openepics.names.util.StructureChoice;
+import org.openepics.names.util.StructureCommand;
 import org.openepics.names.util.StructureElementUtil;
+import org.openepics.names.util.StructureUtil;
 import org.openepics.names.util.ValidateUtil;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -45,13 +48,21 @@ import org.springframework.transaction.annotation.Transactional;
 @Service
 public class DeviceTypeService {
 
+    // note
+    //     structurecommand
+    //         cud - create update delete
+    //         acr - approve cancel reject
+
     private static final Logger LOGGER = Logger.getLogger(DeviceTypeService.class.getName());
 
+    private IDeviceTypeRepository iDeviceTypeRepository;
     private DeviceTypeRepository deviceTypeRepository;
 
     @Autowired
     public DeviceTypeService(
+            IDeviceTypeRepository iDeviceTypeRepository,
             DeviceTypeRepository deviceTypeRepository) {
+        this.iDeviceTypeRepository = iDeviceTypeRepository;
         this.deviceTypeRepository = deviceTypeRepository;
     }
 
@@ -67,7 +78,14 @@ public class DeviceTypeService {
         //         find
         //         approve - update structure to status APPROVED, latest to true
         //         possibly validate that approved
-        //         automatically create name when system structure is approved
+        //         additional
+        //             find out previous to find out what is approved - create update delete
+        //             approve create
+        //                 automatically create name when system structure is approved
+        //                 condition on name and structure entry
+        //                     system structure should exist (uuid), one entry that is not deleted
+        //                     name should not exist (system structure mnemonic)
+        //                 within current transaction
         //     return
         //         structure element for approved structure
 
@@ -97,6 +115,13 @@ public class DeviceTypeService {
         deviceType.setLatest(Boolean.TRUE);
         deviceTypeRepository.updateDeviceType(deviceType);
 
+        // additional
+        // find out previous
+        List<DeviceType> previouses = iDeviceTypeRepository.findPreviousByUuidAndId(uuid, deviceType.getId());
+        StructureCommand structureCommandCUD = StructureUtil.getStructureCommandCUD(previouses, deviceType);
+        DeviceType previous = previouses != null && !previouses.isEmpty() ? previouses.get(0) : null;
+        LOGGER.log(Level.FINE, "approveStructure, structureCommandCUD:        {0}", structureCommandCUD);
+
         LOGGER.log(Level.FINE, "approveStructure, structureElement:           {0}", structureElement);
         return StructureElementUtil.getStructureElementProcessed(deviceType, holder, StructureChoice.STRUCTURE);
     }
diff --git a/src/main/java/org/openepics/names/service/DisciplineService.java b/src/main/java/org/openepics/names/service/DisciplineService.java
index b97c31e7..a3142e3a 100644
--- a/src/main/java/org/openepics/names/service/DisciplineService.java
+++ b/src/main/java/org/openepics/names/service/DisciplineService.java
@@ -24,13 +24,16 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import org.openepics.names.repository.DisciplineRepository;
+import org.openepics.names.repository.IDisciplineRepository;
 import org.openepics.names.repository.model.Discipline;
 import org.openepics.names.rest.beans.Status;
 import org.openepics.names.rest.beans.element.StructureElement;
 import org.openepics.names.rest.beans.element.StructureElementCommand;
 import org.openepics.names.util.HolderSystemDeviceStructure;
 import org.openepics.names.util.StructureChoice;
+import org.openepics.names.util.StructureCommand;
 import org.openepics.names.util.StructureElementUtil;
+import org.openepics.names.util.StructureUtil;
 import org.openepics.names.util.ValidateUtil;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -45,13 +48,21 @@ import org.springframework.transaction.annotation.Transactional;
 @Service
 public class DisciplineService {
 
+    // note
+    //     structurecommand
+    //         cud - create update delete
+    //         acr - approve cancel reject
+
     private static final Logger LOGGER = Logger.getLogger(DisciplineService.class.getName());
 
+    private IDisciplineRepository iDisciplineRepository;
     private DisciplineRepository disciplineRepository;
 
     @Autowired
     public DisciplineService(
+            IDisciplineRepository iDisciplineRepository,
             DisciplineRepository disciplineRepository) {
+        this.iDisciplineRepository = iDisciplineRepository;
         this.disciplineRepository = disciplineRepository;
     }
 
@@ -67,7 +78,14 @@ public class DisciplineService {
         //         find
         //         approve - update structure to status APPROVED, latest to true
         //         possibly validate that approved
-        //         automatically create name when system structure is approved
+        //         additional
+        //             find out previous to find out what is approved - create update delete
+        //             approve create
+        //                 automatically create name when system structure is approved
+        //                 condition on name and structure entry
+        //                     system structure should exist (uuid), one entry that is not deleted
+        //                     name should not exist (system structure mnemonic)
+        //                 within current transaction
         //     return
         //         structure element for approved structure
 
@@ -96,6 +114,13 @@ public class DisciplineService {
         discipline.setLatest(Boolean.TRUE);
         disciplineRepository.updateDiscipline(discipline);
 
+        // additional
+        // find out previous
+        List<Discipline> previouses = iDisciplineRepository.findPreviousByUuidAndId(uuid, discipline.getId());
+        StructureCommand structureCommandCUD = StructureUtil.getStructureCommandCUD(previouses, discipline);
+        Discipline previous = previouses != null && !previouses.isEmpty() ? previouses.get(0) : null;
+        LOGGER.log(Level.FINE, "approveStructure, structureCommandCUD:        {0}", structureCommandCUD);
+
         LOGGER.log(Level.FINE, "approveStructure, structureElement:           {0}", structureElement);
         return StructureElementUtil.getStructureElementProcessed(discipline, holder, StructureChoice.STRUCTURE);
     }
diff --git a/src/main/java/org/openepics/names/service/NamesService.java b/src/main/java/org/openepics/names/service/NamesService.java
index 2cfaeb30..d480eb14 100644
--- a/src/main/java/org/openepics/names/service/NamesService.java
+++ b/src/main/java/org/openepics/names/service/NamesService.java
@@ -86,6 +86,8 @@ public class NamesService {
     //         automatically not show names that do not come into play
     //         = automatically exclude (approved and not latest)
     //         otherwise refer to history
+    //     namecommand
+    //         cud - create update delete
 
     private static final Logger LOGGER = Logger.getLogger(NamesService.class.getName());
 
diff --git a/src/main/java/org/openepics/names/service/StructuresService.java b/src/main/java/org/openepics/names/service/StructuresService.java
index a2eb45e3..86b772f4 100644
--- a/src/main/java/org/openepics/names/service/StructuresService.java
+++ b/src/main/java/org/openepics/names/service/StructuresService.java
@@ -82,6 +82,9 @@ public class StructuresService {
     //         automatically not show structures that do not come into play
     //         = automatically exclude (approved and not latest)
     //         otherwise refer to history
+    //     structurecommand
+    //         cud - create update delete
+    //         acr - approve cancel reject
 
     private static final Logger LOGGER = Logger.getLogger(StructuresService.class.getName());
 
@@ -1053,7 +1056,14 @@ public class StructuresService {
         //                 find
         //                 approve - update structure to status APPROVED, latest to true
         //                 possibly validate that approved
-        //                 automatically create name when system structure is approved
+        //                 additional
+        //                     find out previous to find out what is approved - create update delete
+        //                     approve create
+        //                         automatically create name when system structure is approved
+        //                         condition on name and structure entry
+        //                             system structure should exist (uuid), one entry that is not deleted
+        //                             name should not exist (system structure mnemonic)
+        //                         within current transaction
         //             add to list
         //     return
         //         structure elements for approved structures
diff --git a/src/main/java/org/openepics/names/service/SubsystemService.java b/src/main/java/org/openepics/names/service/SubsystemService.java
index e6d73a40..c2e253db 100644
--- a/src/main/java/org/openepics/names/service/SubsystemService.java
+++ b/src/main/java/org/openepics/names/service/SubsystemService.java
@@ -24,6 +24,7 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import org.apache.commons.lang3.StringUtils;
+import org.openepics.names.repository.ISubsystemRepository;
 import org.openepics.names.repository.SubsystemRepository;
 import org.openepics.names.repository.model.Subsystem;
 import org.openepics.names.rest.beans.Status;
@@ -33,6 +34,7 @@ import org.openepics.names.rest.beans.element.StructureElement;
 import org.openepics.names.rest.beans.element.StructureElementCommand;
 import org.openepics.names.util.HolderSystemDeviceStructure;
 import org.openepics.names.util.StructureChoice;
+import org.openepics.names.util.StructureCommand;
 import org.openepics.names.util.StructureElementUtil;
 import org.openepics.names.util.StructureUtil;
 import org.openepics.names.util.ValidateUtil;
@@ -49,15 +51,23 @@ import org.springframework.transaction.annotation.Transactional;
 @Service
 public class SubsystemService {
 
+    // note
+    //     structurecommand
+    //         cud - create update delete
+    //         acr - approve cancel reject
+
     private static final Logger LOGGER = Logger.getLogger(SubsystemService.class.getName());
 
+    private ISubsystemRepository iSubsystemRepository;
     private SubsystemRepository subsystemRepository;
     private NamesService namesService;
 
     @Autowired
     public SubsystemService(
+            ISubsystemRepository iSubsystemRepository,
             SubsystemRepository subsystemRepository,
             NamesService namesService) {
+        this.iSubsystemRepository = iSubsystemRepository;
         this.subsystemRepository = subsystemRepository;
         this.namesService = namesService;
     }
@@ -74,7 +84,14 @@ public class SubsystemService {
         //         find
         //         approve - update structure to status APPROVED, latest to true
         //         possibly validate that approved
-        //         automatically create name when system structure is approved
+        //         additional
+        //             find out previous to find out what is approved - create update delete
+        //             approve create
+        //                 automatically create name when system structure is approved
+        //                 condition on name and structure entry
+        //                     system structure should exist (uuid), one entry that is not deleted
+        //                     name should not exist (system structure mnemonic)
+        //                 within current transaction
         //     return
         //         structure element for approved structure
 
@@ -104,17 +121,21 @@ public class SubsystemService {
         subsystem.setLatest(Boolean.TRUE);
         subsystemRepository.updateSubsystem(subsystem);
 
-        // automatically create name when system structure is approved (after create)
-        //     condition on name and structure entry
-        //         system structure should exist (uuid), one entry that is not deleted
-        //         name should not exist (system structure mnemonic)
-        // create name within current transaction
-        subsystems = subsystemRepository.readSubsystems(null, Boolean.FALSE, uuid, null, null, null, null, null, null);
-        boolean existsName = !StringUtils.isEmpty(subsystem.getMnemonic()) && namesService.existsName(StructureUtil.getMnemonicPath(subsystem, holder));
-        if (ValidateUtil.isSize(subsystems, 1) && !existsName) {
-            NameElementCommand nameElement = new NameElementCommand(null, subsystem.getUuid(), null, null, StructuresService.SYSTEM_STRUCTURE_ONLY, null);
-            NameElement createdNameElement = namesService.createName(nameElement, holder, processed, processedBy);
-            LOGGER.log(Level.FINE, "approveStructures, nameElement created, name:  {0}", createdNameElement.getName());
+        // additional
+        // find out previous
+        List<Subsystem> previouses = iSubsystemRepository.findPreviousByUuidAndId(uuid, subsystem.getId());
+        StructureCommand structureCommandCUD = StructureUtil.getStructureCommandCUD(previouses, subsystem);
+        Subsystem previous = previouses != null && !previouses.isEmpty() ? previouses.get(0) : null;
+        LOGGER.log(Level.FINE, "approveStructure, structureCommandCUD:        {0}", structureCommandCUD);
+
+        // approve create
+        if (StructureCommand.CREATE.equals(structureCommandCUD)) {
+            boolean existsName = !StringUtils.isEmpty(subsystem.getMnemonic()) && namesService.existsName(StructureUtil.getMnemonicPath(subsystem, holder));
+            if (!existsName) {
+                NameElementCommand nameElement = new NameElementCommand(null, subsystem.getUuid(), null, null, StructuresService.SYSTEM_STRUCTURE_ONLY, null);
+                NameElement createdNameElement = namesService.createName(nameElement, holder, processed, processedBy);
+                LOGGER.log(Level.FINE, "approveStructures, nameElement created, name:  {0}", createdNameElement.getName());
+            }
         }
 
         LOGGER.log(Level.FINE, "approveStructure, structureElement:           {0}", structureElement);
diff --git a/src/main/java/org/openepics/names/service/SystemGroupService.java b/src/main/java/org/openepics/names/service/SystemGroupService.java
index cc829e0e..21accef0 100644
--- a/src/main/java/org/openepics/names/service/SystemGroupService.java
+++ b/src/main/java/org/openepics/names/service/SystemGroupService.java
@@ -24,6 +24,7 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import org.apache.commons.lang3.StringUtils;
+import org.openepics.names.repository.ISystemGroupRepository;
 import org.openepics.names.repository.SystemGroupRepository;
 import org.openepics.names.repository.model.SystemGroup;
 import org.openepics.names.rest.beans.Status;
@@ -33,6 +34,7 @@ import org.openepics.names.rest.beans.element.StructureElement;
 import org.openepics.names.rest.beans.element.StructureElementCommand;
 import org.openepics.names.util.HolderSystemDeviceStructure;
 import org.openepics.names.util.StructureChoice;
+import org.openepics.names.util.StructureCommand;
 import org.openepics.names.util.StructureElementUtil;
 import org.openepics.names.util.StructureUtil;
 import org.openepics.names.util.ValidateUtil;
@@ -49,15 +51,23 @@ import org.springframework.transaction.annotation.Transactional;
 @Service
 public class SystemGroupService {
 
+    // note
+    //     structurecommand
+    //         cud - create update delete
+    //         acr - approve cancel reject
+
     private static final Logger LOGGER = Logger.getLogger(SystemGroupService.class.getName());
 
+    private ISystemGroupRepository iSystemGroupRepository;
     private SystemGroupRepository systemGroupRepository;
     private NamesService namesService;
 
     @Autowired
     public SystemGroupService(
+            ISystemGroupRepository iSystemGroupRepository,
             SystemGroupRepository systemGroupRepository,
             NamesService namesService) {
+        this.iSystemGroupRepository = iSystemGroupRepository;
         this.systemGroupRepository = systemGroupRepository;
         this.namesService = namesService;
     }
@@ -74,7 +84,14 @@ public class SystemGroupService {
         //         find
         //         approve - update structure to status APPROVED, latest to true
         //         possibly validate that approved
-        //         automatically create name when system structure is approved
+        //         additional
+        //             find out previous to find out what is approved - create update delete
+        //             approve create
+        //                 automatically create name when system structure is approved
+        //                 condition on name and structure entry
+        //                     system structure should exist (uuid), one entry that is not deleted
+        //                     name should not exist (system structure mnemonic)
+        //                 within current transaction
         //     return
         //         structure element for approved structure
 
@@ -104,17 +121,22 @@ public class SystemGroupService {
         systemGroup.setLatest(Boolean.TRUE);
         systemGroupRepository.updateSystemGroup(systemGroup);
 
-        // automatically create name when system structure is approved (after create)
-        //     condition on name and structure entry
-        //         system structure should exist (uuid), one entry that is not deleted
-        //         name should not exist (system structure mnemonic)
-        // create name within current transaction
-        systemGroups = systemGroupRepository.readSystemGroups(null, Boolean.FALSE, uuid, null, null, null, null, null);
-        boolean existsName = !StringUtils.isEmpty(systemGroup.getMnemonic()) && namesService.existsName(StructureUtil.getMnemonicPath(systemGroup, holder));
-        if (ValidateUtil.isSize(systemGroups, 1) && !existsName) {
-            NameElementCommand nameElement = new NameElementCommand(null, systemGroup.getUuid(), null, null, StructuresService.SYSTEM_STRUCTURE_ONLY, null);
-            NameElement createdNameElement = namesService.createName(nameElement, holder, processed, processedBy);
-            LOGGER.log(Level.FINE, "approveStructure, nameElement created, name:  {0}", createdNameElement.getName());
+        // additional
+        // find out previous
+        List<SystemGroup> previouses = iSystemGroupRepository.findPreviousByUuidAndId(uuid, systemGroup.getId());
+        StructureCommand structureCommandCUD = StructureUtil.getStructureCommandCUD(previouses, systemGroup);
+        SystemGroup previous = previouses != null && !previouses.isEmpty() ? previouses.get(0) : null;
+        LOGGER.log(Level.INFO, "approveStructure, structureCommandCUD:        {0}", structureCommandCUD);
+
+        // approve create
+        if (StructureCommand.CREATE.equals(structureCommandCUD)) {
+            boolean existsName = !StringUtils.isEmpty(systemGroup.getMnemonic()) && namesService.existsName(StructureUtil.getMnemonicPath(systemGroup, holder));
+            if (!existsName) {
+                NameElementCommand nameElement = new NameElementCommand(null, systemGroup.getUuid(), null, null, StructuresService.SYSTEM_STRUCTURE_ONLY, null);
+                NameElement createdNameElement = namesService.createName(nameElement, holder, processed, processedBy);
+                LOGGER.log(Level.FINE, "approveStructure, nameElement created, name:  {0}", createdNameElement.getName());
+            }
+
         }
 
         LOGGER.log(Level.FINE, "approveStructure, structureElement:           {0}", structureElement);
diff --git a/src/main/java/org/openepics/names/service/SystemService.java b/src/main/java/org/openepics/names/service/SystemService.java
index 870dc869..6366b055 100644
--- a/src/main/java/org/openepics/names/service/SystemService.java
+++ b/src/main/java/org/openepics/names/service/SystemService.java
@@ -24,6 +24,7 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import org.apache.commons.lang3.StringUtils;
+import org.openepics.names.repository.ISystemRepository;
 import org.openepics.names.repository.SystemRepository;
 import org.openepics.names.repository.model.System;
 import org.openepics.names.rest.beans.Status;
@@ -33,6 +34,7 @@ import org.openepics.names.rest.beans.element.StructureElement;
 import org.openepics.names.rest.beans.element.StructureElementCommand;
 import org.openepics.names.util.HolderSystemDeviceStructure;
 import org.openepics.names.util.StructureChoice;
+import org.openepics.names.util.StructureCommand;
 import org.openepics.names.util.StructureElementUtil;
 import org.openepics.names.util.StructureUtil;
 import org.openepics.names.util.ValidateUtil;
@@ -49,15 +51,23 @@ import org.springframework.transaction.annotation.Transactional;
 @Service
 public class SystemService {
 
+    // note
+    //     structurecommand
+    //         cud - create update delete
+    //         acr - approve cancel reject
+
     private static final Logger LOGGER = Logger.getLogger(SystemService.class.getName());
 
+    private ISystemRepository iSystemRepository;
     private SystemRepository systemRepository;
     private NamesService namesService;
 
     @Autowired
     public SystemService(
+            ISystemRepository iSystemRepository,
             SystemRepository systemRepository,
             NamesService namesService) {
+        this.iSystemRepository = iSystemRepository;
         this.systemRepository = systemRepository;
         this.namesService = namesService;
     }
@@ -74,7 +84,14 @@ public class SystemService {
         //         find
         //         approve - update structure to status APPROVED, latest to true
         //         possibly validate that approved
-        //         automatically create name when system structure is approved
+        //         additional
+        //             find out previous to find out what is approved - create update delete
+        //             approve create
+        //                 automatically create name when system structure is approved
+        //                 condition on name and structure entry
+        //                     system structure should exist (uuid), one entry that is not deleted
+        //                     name should not exist (system structure mnemonic)
+        //                 within current transaction
         //     return
         //         structure element for approved structure
 
@@ -104,17 +121,22 @@ public class SystemService {
         system.setLatest(Boolean.TRUE);
         systemRepository.updateSystem(system);
 
-        // automatically create name when system structure is approved (after create)
-        //     condition on name and structure entry
-        //         system structure should exist (uuid), one entry that is not deleted
-        //         name should not exist (system structure mnemonic)
-        // create name within current transaction
-        systems = systemRepository.readSystems(null, Boolean.FALSE, uuid, null, null, null, null, null, null);
-        boolean existsName = !StringUtils.isEmpty(system.getMnemonic()) && namesService.existsName(StructureUtil.getMnemonicPath(system, holder));
-        if (ValidateUtil.isSize(systems, 1) && !existsName) {
-            NameElementCommand nameElement = new NameElementCommand(null, system.getUuid(), null, null, StructuresService.SYSTEM_STRUCTURE_ONLY, null);
-            NameElement createdNameElement = namesService.createName(nameElement, holder, processed, processedBy);
-            LOGGER.log(Level.FINE, "approveStructure, nameElement created, name:  {0}", createdNameElement.getName());
+        // additional
+        // find out previous
+        List<System> previouses = iSystemRepository.findPreviousByUuidAndId(uuid, system.getId());
+        StructureCommand structureCommandCUD = StructureUtil.getStructureCommandCUD(previouses, system);
+        System previous = previouses != null && !previouses.isEmpty() ? previouses.get(0) : null;
+        LOGGER.log(Level.FINE, "approveStructure, structureCommandCUD:        {0}", structureCommandCUD);
+
+        // approve create
+        if (StructureCommand.CREATE.equals(structureCommandCUD)) {
+            boolean existsName = !StringUtils.isEmpty(system.getMnemonic()) && namesService.existsName(StructureUtil.getMnemonicPath(system, holder));
+            if (!existsName) {
+                NameElementCommand nameElement = new NameElementCommand(null, system.getUuid(), null, null, StructuresService.SYSTEM_STRUCTURE_ONLY, null);
+                NameElement createdNameElement = namesService.createName(nameElement, holder, processed, processedBy);
+                LOGGER.log(Level.FINE, "approveStructure, nameElement created, name:  {0}", createdNameElement.getName());
+            }
+
         }
 
         LOGGER.log(Level.FINE, "approveStructure, structureElement:           {0}", structureElement);
diff --git a/src/main/java/org/openepics/names/util/StructureUtil.java b/src/main/java/org/openepics/names/util/StructureUtil.java
index d79cd5b2..c5a6dfa1 100644
--- a/src/main/java/org/openepics/names/util/StructureUtil.java
+++ b/src/main/java/org/openepics/names/util/StructureUtil.java
@@ -27,6 +27,7 @@ import org.apache.commons.lang3.StringUtils;
 import org.openepics.names.repository.model.DeviceGroup;
 import org.openepics.names.repository.model.DeviceType;
 import org.openepics.names.repository.model.Discipline;
+import org.openepics.names.repository.model.Structure;
 import org.openepics.names.repository.model.Subsystem;
 import org.openepics.names.repository.model.System;
 import org.openepics.names.repository.model.SystemGroup;
@@ -277,6 +278,24 @@ public class StructureUtil {
 
     // --------------------------------------------------
 
+    /**
+     * Highly specialized method to find out kind of structure command (create, update, delete).
+     * Intended to be used for services purposes, including notification, in approve, cancel, reject operations.
+     *
+     * @param previous list of previous structures
+     * @param structure structure
+     * @return structure command
+     */
+    public static StructureCommand getStructureCommandCUD(List<?> previous, Structure structure) {
+        if (previous == null || previous.isEmpty()) {
+            return StructureCommand.CREATE;
+        } else if (structure != null && Boolean.TRUE.equals(structure.isDeleted())) {
+            return StructureCommand.DELETE;
+        } else {
+            return StructureCommand.UPDATE;
+        }
+    }
+
     protected static List<UUID> listSystemGroup2Uuid(List<SystemGroup> systemGroups) {
         final List<UUID> listUuid = Lists.newArrayList();
         for (SystemGroup systemGroup : systemGroups) {
-- 
GitLab