package eu.reply.lea.services.yms.task.observer;

import java.io.Serializable;
import java.util.Collections;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.event.Observes;
import javax.inject.Inject;
import javax.persistence.EntityManager;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import org.slf4j.Logger;

import eu.reply.lea.services.masterdata.client.MasterdataServiceException;
import eu.reply.lea.services.yard.exceptions.LoadingUnitActionException;
import eu.reply.lea.services.yard.reference.TransitReference;
import eu.reply.lea.services.yms.task.TaskReference;
import eu.reply.lea.services.yms.task.event.LocationAwareTaskStatusChangedEventInfo;
import eu.reply.lea.services.yms.task.locationaware.LocationAwareTask;
import eu.reply.lea.services.yms.task.queue.QueueHandler;
import eu.reply.lea.services.yms.task.queue.event.TaskDequeueCommand;
import eu.reply.lea.services.yms.task.queue.event.TaskDequeueCommandInfo;
import eu.reply.lea.services.yms.util.ObjectMapperUtility;
import eu.reply.sce.backend.core.event.ConfigurableEventProducer;
import eu.reply.sce.backend.core.event.ModuleEvent;
import eu.reply.sce.backend.core.event.Observer;
import eu.reply.sce.backend.core.jee.configuration.ModuleConfiguration;
import eu.reply.sce.backend.core.jee.configuration.entity.EntityReferenceHandler;
import eu.reply.sce.backend.core.jee.log.Logged;


@Observer
@Logged
@ApplicationScoped
public class QueueObserver implements Serializable {

    @Inject
    @ModuleConfiguration.Module(ModuleConfiguration.Module.CURRENT)
    private EntityManager em;
    
    @Inject
    private EntityReferenceHandler entityReferenceHandler;

    @Inject
    private ConfigurableEventProducer<TaskDequeueCommand> taskDequeueCommandProducer;
    

    public void dequeueTask(
        @Observes @ModuleEvent("externalTaskClosedEvent") final JsonNode taskClosedEvent)
        throws MasterdataServiceException, LoadingUnitActionException, JsonProcessingException {
        LocationAwareTaskStatusChangedEventInfo payload =
            ObjectMapperUtility.getMapper().treeToValue(taskClosedEvent, LocationAwareTaskStatusChangedEventInfo.class);
        final LocationAwareTask<?,?,?>
            task =  entityReferenceHandler.getEntity(payload.getTaskRef(), em);
        if (task.getLocation()!=null) {
            taskDequeueCommandProducer.fire(new TaskDequeueCommand(
                new TaskDequeueCommandInfo(Collections.singletonList(new TaskReference(task)),
                                           Collections.singletonList(task.getLocation()),
                                           new TransitReference(task.getLogisticUnitReference()))));
        }
    }




}
package eu.reply.lea.services.yms.task.sequence;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Index;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.Table;

import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Getter;
import lombok.Setter;

import eu.reply.lea.services.yms.task.locationaware.LocationAwareTask;
import eu.reply.sce.backend.core.entity.EntityReference;
import eu.reply.sce.backend.core.entity.StringCustomizableEntity;

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@Table(indexes = {
    @Index(columnList = "logisticUnitRef_entityId,logisticUnitRef_module,logisticUnitRef_entityName"),
})
@NamedQuery(name = AbstractTasksSequence.Q_FIND_BY_LOGISTIC_UNIT_REF, query = "SELECT ats from AbstractTasksSequence ats where "
                                                                              + "logisticUnitRef.entityId = :logisticUnitEntityId "
                                                                              + "and logisticUnitRef.entityName = :logisticUnitRefEntityName "
                                                                              + "and logisticUnitRef.module = :logisticUnitRefModule")
@Getter
@Setter
public abstract class AbstractTasksSequence extends StringCustomizableEntity
    implements LocationAwareTasksSequence<LocationAwareTask<?, ?, ?>> {

    public static final String Q_FIND_BY_LOGISTIC_UNIT_REF = "AbstractTasksSequence.Q_FIND_BY_LOGISTIC_UNIT_REF";


    @OneToMany(fetch = FetchType.LAZY, mappedBy = "sequence")
    @OrderBy("sequenceNumber ASC")
    private final List<LocationAwareTask<?, ?, ?>> tasks = new ArrayList<>();



    @Embedded
    @AttributeOverrides({@AttributeOverride(name = "entityId", column = @Column(name = "logisticUnitRef_entityId", length = 50)),
        @AttributeOverride(name = "entityName", column = @Column(name = "logisticUnitRef_entityName")),
        @AttributeOverride(name = "module", column = @Column(name = "logisticUnitRef_module", length = 20)),
        @AttributeOverride(name = "businessKey", column = @Column(name = "logisticUnitRef_businessKey")),
        @AttributeOverride(name = "usageType", column = @Column(name = "logisticUnitRef_usageType"))
    })
    private EntityReference logisticUnitRef;

    private boolean blocked = false;

    public List<LocationAwareTask<?, ?, ?>> getTasks() {
        return Collections.unmodifiableList(tasks);
    }

    public boolean addTask(final LocationAwareTask<?, ?, ?> task) {

        if (this.addChild(task, tasks)) {
            task.setSequence(this);
            return true;
        }
        return false;
    }

    public boolean removeTask(final LocationAwareTask<?, ?, ?> task) {
        if (this.removeChild(task, tasks)) {
            task.setSequence(null);
            return true;
        }
        return false;
    }

    @JsonIgnore
    public boolean isAllTasksClosed() {
        return getTasks().stream().allMatch(task -> task.getStatus().isClosed());
    }

    @JsonIgnore
    public List<LocationAwareTask<?, ?, ?>> getSortedSequence() {
        final List<LocationAwareTask<?, ?, ?>> sortedList = this.getTasks().stream().sorted((t1, t2) -> {
            return t1.getSequenceNumber().compareTo(t2.getSequenceNumber());
        }).collect(Collectors.toList());
        return sortedList;
    }

    @JsonIgnore
    protected List<LocationAwareTask<?, ?, ?>> getQueueableTasks(List<LocationAwareTask<?, ?, ?>> sortedSequence, int sequenceNumber,
                                                        boolean inclusive) {
        List<LocationAwareTask<?, ?, ?>> nextTasksQueueable = sortedSequence.stream()
            .filter(t -> inclusive ? t.getSequenceNumber() >= sequenceNumber
                                   : t.getSequenceNumber() > sequenceNumber)
            .filter(LocationAwareTask::isQueueable)
            .collect(Collectors.toList());


        return nextTasksQueueable;
    }

    @JsonIgnore
    public List<LocationAwareTask<?, ?, ?>> getActiveTasks() {
        return this.getTasks().stream()
            .filter(t -> t.getStatus().isActive())
            .collect(Collectors.toList());
    }

    @JsonIgnore
    public List<LocationAwareTask<?, ?, ?>> getQueueableTasks() {
        List<LocationAwareTask<?, ?, ?>> sortedSequence = getSortedSequence();
        return getQueueableTasks(sortedSequence, 0, true);
    }

}
COnsidering the code above, wheneever a task is closed (externalTaskClosedEvent) a dequeue for that location is performed, 
But this is wrong becuase if i have two tasks on the same location the dequeue should not happen, but the logistic unit should remain in the same position.

How can i solve this problem?
think about it a lot more, and provide me with a more compelte answer
Maybe it's simpler, here i can check if there are more tasks in the same location to do and fire only if there are, but you should refactor considering the DD principles, which are not completely respected here